11 #include "kmreaderwin.h"
13 #include "globalsettings.h"
14 #include "kmversion.h"
15 #include "kmmainwidget.h"
16 #include "kmreadermainwin.h"
17 #include <libkdepim/kfileio.h>
18 #include "kmfolderindex.h"
19 #include "kmcommands.h"
20 #include "kmmsgpartdlg.h"
21 #include "mailsourceviewer.h"
22 using KMail::MailSourceViewer;
24 #include "kmmsgdict.h"
25 #include "messagesender.h"
26 #include "kcursorsaver.h"
28 #include "vcardviewer.h"
29 using KMail::VCardViewer;
30 #include "objecttreeparser.h"
31 using KMail::ObjectTreeParser;
32 #include "partmetadata.h"
33 using KMail::PartMetaData;
34 #include "attachmentstrategy.h"
35 using KMail::AttachmentStrategy;
36 #include "headerstrategy.h"
37 using KMail::HeaderStrategy;
38 #include "headerstyle.h"
40 #include "khtmlparthtmlwriter.h"
42 using KMail::KHtmlPartHtmlWriter;
43 #include "htmlstatusbar.h"
45 #include "folderjob.h"
46 using KMail::FolderJob;
47 #include "csshelper.h"
48 using KMail::CSSHelper;
50 using KMail::ISubject;
51 #include "urlhandlermanager.h"
53 #include "interfaces/observable.h"
55 #include "kmheaders.h"
57 #include "broadcaststatus.h"
59 #include <kmime_mdn.h>
60 using namespace KMime;
61 #ifdef KMAIL_READER_HTML_DEBUG
62 #include "filehtmlwriter.h"
63 using KMail::FileHtmlWriter;
64 #include "teehtmlwriter.h"
68 #include <kasciistringtools.h>
69 #include <kstringhandler.h>
71 #include <mimelib/mimepp.h>
72 #include <mimelib/body.h>
73 #include <mimelib/utility.h>
75 #include <kleo/specialjob.h>
76 #include <kleo/cryptobackend.h>
77 #include <kleo/cryptobackendfactory.h>
80 #include <kabc/addressee.h>
81 #include <kabc/vcardconverter.h>
84 #include <khtml_part.h>
85 #include <khtmlview.h>
86 #include <dom/html_element.h>
87 #include <dom/html_block.h>
88 #include <dom/html_document.h>
89 #include <dom/dom_string.h>
90 #include <dom/dom_exception.h>
92 #include <kapplication.h>
94 #include <kuserprofile.h>
95 #include <kcharsets.h>
96 #include <kpopupmenu.h>
97 #include <kstandarddirs.h>
100 #include <kfiledialog.h>
102 #include <kmessagebox.h>
103 #include <kglobalsettings.h>
105 #include <ktempfile.h>
106 #include <kprocess.h>
109 #include <kiconloader.h>
110 #include <kmdcodec.h>
111 #include <kasciistricmp.h>
112 #include <kurldrag.h>
114 #include <tqclipboard.h>
116 #include <tqtextcodec.h>
117 #include <tqpaintdevicemetrics.h>
118 #include <tqlayout.h>
120 #include <tqsplitter.h>
129 #include <sys/stat.h>
139 class NewByteArray :
public TQByteArray
142 NewByteArray &appendNULL();
143 NewByteArray &operator+=(
const char * );
144 NewByteArray &operator+=(
const TQByteArray & );
145 NewByteArray &operator+=(
const TQCString & );
146 TQByteArray& qByteArray();
149 NewByteArray& NewByteArray::appendNULL()
151 TQByteArray::detach();
153 if ( !TQByteArray::resize( len1 + 1 ) )
155 *(data() + len1) =
'\0';
158 NewByteArray& NewByteArray::operator+=(
const char * newData )
162 TQByteArray::detach();
164 uint len2 = tqstrlen( newData );
165 if ( !TQByteArray::resize( len1 + len2 ) )
167 memcpy( data() + len1, newData, len2 );
170 NewByteArray& NewByteArray::operator+=(
const TQByteArray & newData )
172 if ( newData.isNull() )
174 TQByteArray::detach();
176 uint len2 = newData.size();
177 if ( !TQByteArray::resize( len1 + len2 ) )
179 memcpy( data() + len1, newData.data(), len2 );
182 NewByteArray& NewByteArray::operator+=(
const TQCString & newData )
184 if ( newData.isEmpty() )
186 TQByteArray::detach();
188 uint len2 = newData.length();
189 if ( !TQByteArray::resize( len1 + len2 ) )
191 memcpy( data() + len1, newData.data(), len2 );
194 TQByteArray& NewByteArray::qByteArray()
196 return *((TQByteArray*)
this);
203 void KMReaderWin::objectTreeToDecryptedMsg( partNode* node,
204 NewByteArray& resultingData,
206 bool weAreReplacingTheRootNode,
209 kdDebug(5006) << TQString(
"-------------------------------------------------" ) << endl;
210 kdDebug(5006) << TQString(
"KMReaderWin::objectTreeToDecryptedMsg( %1 ) START").arg( recCount ) << endl;
213 kdDebug(5006) << node->typeString() <<
'/' << node->subTypeString() << endl;
215 partNode* curNode = node;
216 partNode* dataNode = curNode;
217 partNode * child = node->firstChild();
218 const bool bIsMultipart = node->type() == DwMime::kTypeMultipart ;
219 bool bKeepPartAsIs =
false;
221 switch( curNode->type() ){
222 case DwMime::kTypeMultipart: {
223 switch( curNode->subType() ){
224 case DwMime::kSubtypeSigned: {
225 bKeepPartAsIs =
true;
228 case DwMime::kSubtypeEncrypted: {
236 case DwMime::kTypeMessage: {
237 switch( curNode->subType() ){
238 case DwMime::kSubtypeRfc822: {
246 case DwMime::kTypeApplication: {
247 switch( curNode->subType() ){
248 case DwMime::kSubtypeOctetStream: {
253 case DwMime::kSubtypePkcs7Signature: {
256 bKeepPartAsIs =
true;
259 case DwMime::kSubtypePkcs7Mime: {
262 if ( child && curNode->encryptionState() != KMMsgNotEncrypted )
272 DwHeaders& rootHeaders( theMessage.
headers() );
273 DwBodyPart * part = dataNode->dwPart() ? dataNode->dwPart() : 0;
275 (part && part->hasHeaders())
277 : ( (weAreReplacingTheRootNode || !dataNode->parentNode())
280 if( dataNode == curNode ) {
281 kdDebug(5006) <<
"dataNode == curNode: Save curNode without replacing it." << endl;
287 if( dataNode->parentNode() && !weAreReplacingTheRootNode ) {
288 kdDebug(5006) <<
"dataNode is NOT replacing the root node: Store the headers." << endl;
289 resultingData += headers->AsString().c_str();
290 }
else if( weAreReplacingTheRootNode && part && part->hasHeaders() ){
291 kdDebug(5006) <<
"dataNode replace the root node: Do NOT store the headers but change" << endl;
292 kdDebug(5006) <<
" the Message's headers accordingly." << endl;
293 kdDebug(5006) <<
" old Content-Type = " << rootHeaders.ContentType().AsString().c_str() << endl;
294 kdDebug(5006) <<
" new Content-Type = " << headers->ContentType( ).AsString().c_str() << endl;
295 rootHeaders.ContentType() = headers->ContentType();
296 theMessage.setContentTransferEncodingStr(
297 headers->HasContentTransferEncoding()
298 ? headers->ContentTransferEncoding().AsString().c_str()
300 rootHeaders.ContentDescription() = headers->ContentDescription();
301 rootHeaders.ContentDisposition() = headers->ContentDisposition();
306 if ( bKeepPartAsIs ) {
307 resultingData += dataNode->encodedBody();
311 if( headers && bIsMultipart && dataNode->firstChild() ) {
312 kdDebug(5006) <<
"is valid Multipart, processing children:" << endl;
313 TQCString boundary = headers->ContentType().Boundary().c_str();
314 curNode = dataNode->firstChild();
317 kdDebug(5006) <<
"--boundary" << endl;
318 if( resultingData.size() &&
319 (
'\n' != resultingData.at( resultingData.size()-1 ) ) )
320 resultingData += TQCString(
"\n" );
321 resultingData += TQCString(
"\n" );
322 resultingData +=
"--";
323 resultingData += boundary;
324 resultingData +=
"\n";
328 objectTreeToDecryptedMsg( curNode,
333 curNode = curNode->nextSibling();
335 kdDebug(5006) <<
"--boundary--" << endl;
336 resultingData +=
"\n--";
337 resultingData += boundary;
338 resultingData +=
"--\n\n";
339 kdDebug(5006) <<
"Multipart processing children - DONE" << endl;
342 kdDebug(5006) <<
"is Simple part or invalid Multipart, storing body data .. DONE" << endl;
343 resultingData += part->Body().AsString().c_str();
347 kdDebug(5006) <<
"dataNode != curNode: Replace curNode by dataNode." << endl;
348 bool rootNodeReplaceFlag = weAreReplacingTheRootNode || !curNode->parentNode();
349 if( rootNodeReplaceFlag ) {
350 kdDebug(5006) <<
" Root node will be replaced." << endl;
352 kdDebug(5006) <<
" Root node will NOT be replaced." << endl;
356 objectTreeToDecryptedMsg( dataNode,
363 kdDebug(5006) << TQString(
"\nKMReaderWin::objectTreeToDecryptedMsg( %1 ) END").arg( recCount ) << endl;
387 void KMReaderWin::createWidgets() {
388 TQVBoxLayout * vlay =
new TQVBoxLayout(
this );
389 mSplitter =
new TQSplitter( Qt::Vertical,
this,
"mSplitter" );
390 vlay->addWidget( mSplitter );
391 mMimePartTree =
new KMMimePartTree(
this, mSplitter,
"mMimePartTree" );
392 mBox =
new TQHBox( mSplitter,
"mBox" );
393 setStyleDependantFrameWidth();
394 mBox->setFrameStyle( mMimePartTree->frameStyle() );
396 mViewer =
new KHTMLPart( mBox,
"mViewer" );
397 mSplitter->setOpaqueResize( KGlobalSettings::opaqueResize() );
398 mSplitter->setResizeMode( mMimePartTree, TQSplitter::KeepSize );
401 const int KMReaderWin::delay = 150;
404 KMReaderWin::KMReaderWin(TQWidget *aParent,
405 TQWidget *mainWindow,
406 KActionCollection* actionCollection,
409 : TQWidget(aParent, aName, aFlags | TQt::WDestructiveClose),
410 mSerNumOfOriginalMessage( 0 ),
412 mAttachmentStrategy( 0 ),
413 mHeaderStrategy( 0 ),
415 mUpdateReaderWinTimer( 0,
"mUpdateReaderWinTimer" ),
416 mResizeTimer( 0,
"mResizeTimer" ),
417 mDelayedMarkTimer( 0,
"mDelayedMarkTimer" ),
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 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 mMimeTreeAtBottom =
true;
452 mWaitingForSerNum = 0;
456 mShowColorbar =
false;
460 createActions( actionCollection );
464 mHtmlOverride =
false;
465 mHtmlLoadExtOverride =
false;
467 mLevelQuote = GlobalSettings::self()->collapseQuoteLevelSpin() - 1;
469 connect( &mUpdateReaderWinTimer, TQT_SIGNAL(timeout()),
470 TQT_TQOBJECT(
this), TQT_SLOT(updateReaderWin()) );
471 connect( &mResizeTimer, TQT_SIGNAL(timeout()),
472 TQT_TQOBJECT(
this), TQT_SLOT(slotDelayedResize()) );
473 connect( &mDelayedMarkTimer, TQT_SIGNAL(timeout()),
474 TQT_TQOBJECT(
this), TQT_SLOT(slotTouchMessage()) );
478 void KMReaderWin::createActions( KActionCollection * ac ) {
482 KRadioAction *raction = 0;
485 KActionMenu *headerMenu =
486 new KActionMenu( i18n(
"View->",
"&Headers"), ac,
"view_headers" );
487 headerMenu->setToolTip( i18n(
"Choose display style of message headers") );
489 connect( headerMenu, TQT_SIGNAL(activated()),
490 TQT_TQOBJECT(
this), TQT_SLOT(slotCycleHeaderStyles()) );
492 raction =
new KRadioAction( i18n(
"View->headers->",
"&Enterprise Headers"), 0,
493 TQT_TQOBJECT(
this), TQT_SLOT(slotEnterpriseHeaders()),
494 ac,
"view_headers_enterprise" );
495 raction->setToolTip( i18n(
"Show the list of headers in Enterprise style") );
496 raction->setExclusiveGroup(
"view_headers_group" );
497 headerMenu->insert(raction);
499 raction =
new KRadioAction( i18n(
"View->headers->",
"&Fancy Headers"), 0,
500 TQT_TQOBJECT(
this), TQT_SLOT(slotFancyHeaders()),
501 ac,
"view_headers_fancy" );
502 raction->setToolTip( i18n(
"Show the list of headers in a fancy format") );
503 raction->setExclusiveGroup(
"view_headers_group" );
504 headerMenu->insert( raction );
506 raction =
new KRadioAction( i18n(
"View->headers->",
"&Brief Headers"), 0,
507 TQT_TQOBJECT(
this), TQT_SLOT(slotBriefHeaders()),
508 ac,
"view_headers_brief" );
509 raction->setToolTip( i18n(
"Show brief list of message headers") );
510 raction->setExclusiveGroup(
"view_headers_group" );
511 headerMenu->insert( raction );
513 raction =
new KRadioAction( i18n(
"View->headers->",
"&Standard Headers"), 0,
514 TQT_TQOBJECT(
this), TQT_SLOT(slotStandardHeaders()),
515 ac,
"view_headers_standard" );
516 raction->setToolTip( i18n(
"Show standard list of message headers") );
517 raction->setExclusiveGroup(
"view_headers_group" );
518 headerMenu->insert( raction );
520 raction =
new KRadioAction( i18n(
"View->headers->",
"&Long Headers"), 0,
521 TQT_TQOBJECT(
this), TQT_SLOT(slotLongHeaders()),
522 ac,
"view_headers_long" );
523 raction->setToolTip( i18n(
"Show long list of message headers") );
524 raction->setExclusiveGroup(
"view_headers_group" );
525 headerMenu->insert( raction );
527 raction =
new KRadioAction( i18n(
"View->headers->",
"&All Headers"), 0,
528 TQT_TQOBJECT(
this), TQT_SLOT(slotAllHeaders()),
529 ac,
"view_headers_all" );
530 raction->setToolTip( i18n(
"Show all message headers") );
531 raction->setExclusiveGroup(
"view_headers_group" );
532 headerMenu->insert( raction );
535 KActionMenu *attachmentMenu =
536 new KActionMenu( i18n(
"View->",
"&Attachments"), ac,
"view_attachments" );
537 attachmentMenu->setToolTip( i18n(
"Choose display style of attachments") );
538 connect( attachmentMenu, TQT_SIGNAL(activated()),
539 TQT_TQOBJECT(
this), TQT_SLOT(slotCycleAttachmentStrategy()) );
541 raction =
new KRadioAction( i18n(
"View->attachments->",
"&As Icons"), 0,
542 TQT_TQOBJECT(
this), TQT_SLOT(slotIconicAttachments()),
543 ac,
"view_attachments_as_icons" );
544 raction->setToolTip( i18n(
"Show all attachments as icons. Click to see them.") );
545 raction->setExclusiveGroup(
"view_attachments_group" );
546 attachmentMenu->insert( raction );
548 raction =
new KRadioAction( i18n(
"View->attachments->",
"&Smart"), 0,
549 TQT_TQOBJECT(
this), TQT_SLOT(slotSmartAttachments()),
550 ac,
"view_attachments_smart" );
551 raction->setToolTip( i18n(
"Show attachments as suggested by sender.") );
552 raction->setExclusiveGroup(
"view_attachments_group" );
553 attachmentMenu->insert( raction );
555 raction =
new KRadioAction( i18n(
"View->attachments->",
"&Inline"), 0,
556 TQT_TQOBJECT(
this), TQT_SLOT(slotInlineAttachments()),
557 ac,
"view_attachments_inline" );
558 raction->setToolTip( i18n(
"Show all attachments inline (if possible)") );
559 raction->setExclusiveGroup(
"view_attachments_group" );
560 attachmentMenu->insert( raction );
562 raction =
new KRadioAction( i18n(
"View->attachments->",
"&Hide"), 0,
563 TQT_TQOBJECT(
this), TQT_SLOT(slotHideAttachments()),
564 ac,
"view_attachments_hide" );
565 raction->setToolTip( i18n(
"Do not show attachments in the message viewer") );
566 raction->setExclusiveGroup(
"view_attachments_group" );
567 attachmentMenu->insert( raction );
569 mHeaderOnlyAttachmentsAction =
new KRadioAction( i18n(
"View->attachments->",
"In Header &Only" ), 0,
570 TQT_TQOBJECT(
this), TQT_SLOT( slotHeaderOnlyAttachments() ),
571 ac,
"view_attachments_headeronly" );
572 mHeaderOnlyAttachmentsAction->setToolTip( i18n(
"Show Attachments only in the header of the mail" ) );
573 mHeaderOnlyAttachmentsAction->setExclusiveGroup(
"view_attachments_group" );
574 attachmentMenu->insert( mHeaderOnlyAttachmentsAction );
577 mSelectEncodingAction =
new KSelectAction( i18n(
"&Set Encoding" ),
"charset", 0,
578 TQT_TQOBJECT(
this), TQT_SLOT( slotSetEncoding() ),
580 TQStringList encodings = KMMsgBase::supportedEncodings(
false );
581 encodings.prepend( i18n(
"Auto" ) );
582 mSelectEncodingAction->setItems( encodings );
583 mSelectEncodingAction->setCurrentItem( 0 );
585 mMailToComposeAction =
new KAction( i18n(
"New Message To..."),
"mail_new",
586 0, TQT_TQOBJECT(
this), TQT_SLOT(slotMailtoCompose()), ac,
588 mMailToReplyAction =
new KAction( i18n(
"Reply To..."),
"mail_reply",
591 mMailToForwardAction =
new KAction( i18n(
"Forward To..."),
"mail_forward",
592 0, TQT_TQOBJECT(
this), TQT_SLOT(slotMailtoForward()), ac,
594 mAddAddrBookAction =
new KAction( i18n(
"Add to Address Book"),
595 0, TQT_TQOBJECT(
this), TQT_SLOT(slotMailtoAddAddrBook()),
596 ac,
"add_addr_book" );
597 mOpenAddrBookAction =
new KAction( i18n(
"Open in Address Book"),
598 0, TQT_TQOBJECT(
this), TQT_SLOT(slotMailtoOpenAddrBook()),
599 ac,
"openin_addr_book" );
600 mCopyAction = KStdAction::copy( TQT_TQOBJECT(
this), TQT_SLOT(
slotCopySelectedText()), ac,
"kmail_copy");
601 mSelectAllAction =
new KAction( i18n(
"Select All Text"), CTRL+SHIFT+Key_A, TQT_TQOBJECT(
this),
602 TQT_SLOT(
selectAll()), ac,
"mark_all_text" );
603 mCopyURLAction =
new KAction( i18n(
"Copy Link Address"), 0, TQT_TQOBJECT(
this),
605 mUrlOpenAction =
new KAction( i18n(
"Open URL"), 0, TQT_TQOBJECT(
this),
607 mAddBookmarksAction =
new KAction( i18n(
"Bookmark This Link"),
609 0, TQT_TQOBJECT(
this), TQT_SLOT(slotAddBookmarks()),
610 ac,
"add_bookmarks" );
611 mUrlSaveAsAction =
new KAction( i18n(
"Save Link As..."), 0, TQT_TQOBJECT(
this),
614 mToggleFixFontAction =
new KToggleAction( i18n(
"Use Fi&xed Font"),
616 ac,
"toggle_fixedfont" );
618 mStartIMChatAction =
new KAction( i18n(
"Chat &With..."), 0, TQT_TQOBJECT(
this),
619 TQT_SLOT(
slotIMChat()), ac,
"start_im_chat" );
623 KRadioAction *KMReaderWin::actionForHeaderStyle(
const HeaderStyle * style,
const HeaderStrategy * strategy ) {
624 if ( !mActionCollection )
626 const char * actionName = 0;
627 if ( style == HeaderStyle::enterprise() )
628 actionName =
"view_headers_enterprise";
629 if ( style == HeaderStyle::fancy() )
630 actionName =
"view_headers_fancy";
631 else if ( style == HeaderStyle::brief() )
632 actionName =
"view_headers_brief";
633 else if ( style == HeaderStyle::plain() ) {
634 if ( strategy == HeaderStrategy::standard() )
635 actionName =
"view_headers_standard";
636 else if ( strategy == HeaderStrategy::rich() )
637 actionName =
"view_headers_long";
638 else if ( strategy == HeaderStrategy::all() )
639 actionName =
"view_headers_all";
642 return static_cast<KRadioAction*
>(mActionCollection->action(actionName));
647 KRadioAction *KMReaderWin::actionForAttachmentStrategy(
const AttachmentStrategy * as ) {
648 if ( !mActionCollection )
650 const char * actionName = 0;
651 if ( as == AttachmentStrategy::iconic() )
652 actionName =
"view_attachments_as_icons";
653 else if ( as == AttachmentStrategy::smart() )
654 actionName =
"view_attachments_smart";
655 else if ( as == AttachmentStrategy::inlined() )
656 actionName =
"view_attachments_inline";
657 else if ( as == AttachmentStrategy::hidden() )
658 actionName =
"view_attachments_hide";
659 else if ( as == AttachmentStrategy::headerOnly() )
660 actionName =
"view_attachments_headeronly";
663 return static_cast<KRadioAction*
>(mActionCollection->action(actionName));
668 void KMReaderWin::slotEnterpriseHeaders() {
670 HeaderStrategy::rich() );
671 if( !mExternalWindow )
675 void KMReaderWin::slotFancyHeaders() {
677 HeaderStrategy::rich() );
678 if( !mExternalWindow )
682 void KMReaderWin::slotBriefHeaders() {
684 HeaderStrategy::brief() );
685 if( !mExternalWindow )
689 void KMReaderWin::slotStandardHeaders() {
691 HeaderStrategy::standard());
695 void KMReaderWin::slotLongHeaders() {
697 HeaderStrategy::rich() );
698 if( !mExternalWindow )
702 void KMReaderWin::slotAllHeaders() {
704 HeaderStrategy::all() );
705 if( !mExternalWindow )
709 void KMReaderWin::slotLevelQuote(
int l )
716 void KMReaderWin::slotCycleHeaderStyles() {
720 const char * actionName = 0;
721 if ( style == HeaderStyle::enterprise() ) {
723 actionName =
"view_headers_fancy";
725 if ( style == HeaderStyle::fancy() ) {
727 actionName =
"view_headers_brief";
728 }
else if ( style == HeaderStyle::brief() ) {
729 slotStandardHeaders();
730 actionName =
"view_headers_standard";
731 }
else if ( style == HeaderStyle::plain() ) {
732 if ( strategy == HeaderStrategy::standard() ) {
734 actionName =
"view_headers_long";
735 }
else if ( strategy == HeaderStrategy::rich() ) {
737 actionName =
"view_headers_all";
738 }
else if ( strategy == HeaderStrategy::all() ) {
739 slotEnterpriseHeaders();
740 actionName =
"view_headers_enterprise";
745 static_cast<KRadioAction*
>( mActionCollection->action( actionName ) )->setChecked(
true );
749 void KMReaderWin::slotIconicAttachments() {
750 setAttachmentStrategy( AttachmentStrategy::iconic() );
753 void KMReaderWin::slotSmartAttachments() {
754 setAttachmentStrategy( AttachmentStrategy::smart() );
757 void KMReaderWin::slotInlineAttachments() {
758 setAttachmentStrategy( AttachmentStrategy::inlined() );
761 void KMReaderWin::slotHideAttachments() {
762 setAttachmentStrategy( AttachmentStrategy::hidden() );
765 void KMReaderWin::slotHeaderOnlyAttachments() {
766 setAttachmentStrategy( AttachmentStrategy::headerOnly() );
769 void KMReaderWin::slotCycleAttachmentStrategy() {
773 action->setChecked(
true );
778 KMReaderWin::~KMReaderWin()
780 clearBodyPartMementos();
781 delete mHtmlWriter; mHtmlWriter = 0;
783 if (mAutoDelete)
delete message();
784 delete mRootNode; mRootNode = 0;
790 void KMReaderWin::slotMessageArrived(
KMMessage *msg )
792 if (msg && ((KMMsgBase*)msg)->isMessage()) {
793 if ( msg->getMsgSerNum() == mWaitingForSerNum ) {
819 kdDebug(5006) <<
"KMReaderWin::update - no updated part" << endl;
822 partNode* node = mRootNode->findNodeForDwPart( msg->
lastUpdatedPart() );
824 kdDebug(5006) <<
"KMReaderWin::update - can't find node for part" << endl;
831 ::chmod( TQFile::encodeName( mAtmCurrentName ), S_IRWXU );
832 TQByteArray data = node->msgPart().bodyDecodedBinary();
833 size_t size = data.size();
834 if ( node->msgPart().type() == DwMime::kTypeText && size) {
837 KPIM::kBytesToFile( data.data(), size, mAtmCurrentName,
false,
false, false );
838 ::chmod( TQFile::encodeName( mAtmCurrentName ), S_IRUSR );
846 for (TQStringList::Iterator it = mTempFiles.begin(); it != mTempFiles.end();
852 for (TQStringList::Iterator it = mTempDirs.begin(); it != mTempDirs.end();
855 TQDir(*it).rmdir(*it);
864 if (e->type() == TQEvent::ApplicationPaletteChange)
867 mCSSHelper =
new KMail::CSSHelper( TQPaintDeviceMetrics( mViewer->view() ) );
880 const KConfigGroup mdnGroup( KMKernel::config(),
"MDN" );
881 KConfigGroup reader( KMKernel::config(),
"Reader" );
884 mCSSHelper =
new KMail::CSSHelper( TQPaintDeviceMetrics( mViewer->view() ) );
886 mNoMDNsWhenEncrypted = mdnGroup.readBoolEntry(
"not-send-when-encrypted",
true );
888 mUseFixedFont = reader.readBoolEntry(
"useFixedFont",
false );
889 if ( mToggleFixFontAction )
890 mToggleFixFontAction->setChecked( mUseFixedFont );
892 mHtmlMail = reader.readBoolEntry(
"htmlMail",
false );
893 mHtmlLoadExternal = reader.readBoolEntry(
"htmlLoadExternal",
false );
896 HeaderStrategy::create( reader.readEntry(
"header-set-displayed",
"rich" ) ) );
897 KRadioAction *raction = actionForHeaderStyle( headerStyle(),
headerStrategy() );
899 raction->setChecked(
true );
901 setAttachmentStrategy( AttachmentStrategy::create( reader.readEntry(
"attachment-strategy",
"smart" ) ) );
904 raction->setChecked(
true );
908 mShowColorbar = reader.readBoolEntry(
"showColorbar", Kpgp::Module::getKpgp()->usePGP() );
912 reader.writeEntry(
"showColorbar", mShowColorbar );
914 mMimeTreeAtBottom = reader.readEntry(
"MimeTreeLocation",
"bottom" ) !=
"top";
915 const TQString s = reader.readEntry(
"MimeTreeMode",
"smart" );
918 else if ( s ==
"always" )
923 const int mimeH = reader.readNumEntry(
"MimePaneHeight", 100 );
924 const int messageH = reader.readNumEntry(
"MessagePaneHeight", 180 );
925 mSplitterSizes.clear();
926 if ( mMimeTreeAtBottom )
927 mSplitterSizes << messageH << mimeH;
929 mSplitterSizes << mimeH << messageH;
933 readGlobalOverrideCodec();
941 void KMReaderWin::adjustLayout() {
942 if ( mMimeTreeAtBottom )
943 mSplitter->moveToLast( mMimePartTree );
945 mSplitter->moveToFirst( mMimePartTree );
946 mSplitter->setSizes( mSplitterSizes );
948 if ( mMimeTreeMode == 2 && mMsgDisplay )
949 mMimePartTree->show();
951 mMimePartTree->hide();
953 if ( mShowColorbar && mMsgDisplay )
960 void KMReaderWin::saveSplitterSizes( KConfigBase & c )
const {
961 if ( !mSplitter || !mMimePartTree )
963 if ( mMimePartTree->isHidden() )
966 c.writeEntry(
"MimePaneHeight", mSplitter->sizes()[ mMimeTreeAtBottom ? 1 : 0 ] );
967 c.writeEntry(
"MessagePaneHeight", mSplitter->sizes()[ mMimeTreeAtBottom ? 0 : 1 ] );
972 KConfigGroup reader( KMKernel::config(),
"Reader" );
974 reader.writeEntry(
"useFixedFont", mUseFixedFont );
976 reader.writeEntry(
"header-style", headerStyle()->name() );
978 reader.writeEntry(
"header-set-displayed",
headerStrategy()->name() );
982 saveSplitterSizes( reader );
985 kmkernel->slotRequestConfigSync();
991 mViewer->widget()->setFocusPolicy(TQ_WheelFocus);
993 mViewer->setPluginsEnabled(
false);
994 mViewer->setJScriptEnabled(
false);
995 mViewer->setJavaEnabled(
false);
996 mViewer->setMetaRefreshEnabled(
false);
997 mViewer->setURLCursor(KCursor::handCursor());
999 mViewer->view()->setLineWidth(0);
1001 mViewer->view()->viewport()->installEventFilter(
this );
1004 #ifdef KMAIL_READER_HTML_DEBUG
1005 mHtmlWriter =
new TeeHtmlWriter(
new FileHtmlWriter( TQString() ),
1006 new KHtmlPartHtmlWriter( mViewer, 0 ) );
1008 mHtmlWriter =
new KHtmlPartHtmlWriter( mViewer, 0 );
1011 connect(mViewer->browserExtension(),
1012 TQT_SIGNAL(openURLRequest(
const KURL &,
const KParts::URLArgs &)),
this,
1014 connect(mViewer->browserExtension(),
1015 TQT_SIGNAL(createNewWindow(
const KURL &,
const KParts::URLArgs &)),
this,
1017 connect(mViewer,TQT_SIGNAL(
popupMenu(
const TQString &,
const TQPoint &)),
1018 TQT_SLOT(
slotUrlPopup(
const TQString &,
const TQPoint &)));
1019 connect( kmkernel->imProxy(), TQT_SIGNAL( sigContactPresenceChanged(
const TQString & ) ),
1020 TQT_TQOBJECT(
this), TQT_SLOT( contactStatusChanged(
const TQString & ) ) );
1021 connect( kmkernel->imProxy(), TQT_SIGNAL( sigPresenceInfoExpired() ),
1025 void KMReaderWin::contactStatusChanged(
const TQString &uid)
1029 DOM::NodeList presenceNodes = mViewer->htmlDocument()
1030 .getElementsByName( DOM::DOMString( TQString::fromLatin1(
"presence-") + uid ) );
1031 for (
unsigned int i = 0; i < presenceNodes.length(); ++i ) {
1032 DOM::Node n = presenceNodes.item( i );
1033 kdDebug( 5006 ) <<
"name is " << n.nodeName().string() << endl;
1034 kdDebug( 5006 ) <<
"value of content was " << n.firstChild().nodeValue().string() << endl;
1035 TQString newPresence = kmkernel->imProxy()->presenceString( uid );
1036 if ( newPresence.isNull() )
1037 newPresence = TQString::fromLatin1(
"ENOIMRUNNING" );
1038 n.firstChild().setNodeValue( newPresence );
1044 void KMReaderWin::setAttachmentStrategy(
const AttachmentStrategy * strategy ) {
1045 mAttachmentStrategy = strategy ? strategy : AttachmentStrategy::smart();
1050 const HeaderStrategy * strategy ) {
1051 mHeaderStyle = style ? style : HeaderStyle::fancy();
1052 mHeaderStrategy = strategy ? strategy : HeaderStrategy::rich();
1053 if ( mHeaderOnlyAttachmentsAction ) {
1054 const bool styleHasAttachmentQuickList = mHeaderStyle == HeaderStyle::fancy() ||
1055 mHeaderStyle == HeaderStyle::enterprise();
1056 mHeaderOnlyAttachmentsAction->setEnabled( styleHasAttachmentQuickList );
1057 if ( !styleHasAttachmentQuickList && mAttachmentStrategy == AttachmentStrategy::headerOnly() ) {
1060 setAttachmentStrategy( AttachmentStrategy::smart() );
1069 if ( encoding == mOverrideEncoding )
1072 mOverrideEncoding = encoding;
1073 if ( mSelectEncodingAction ) {
1074 if ( encoding.isEmpty() ) {
1075 mSelectEncodingAction->setCurrentItem( 0 );
1078 TQStringList encodings = mSelectEncodingAction->items();
1080 for ( TQStringList::const_iterator it = encodings.begin(), end = encodings.end(); it != end; ++it, ++i ) {
1081 if ( KGlobal::charsets()->encodingForName( *it ) == encoding ) {
1082 mSelectEncodingAction->setCurrentItem( i );
1086 if ( i == encodings.size() ) {
1088 kdWarning(5006) <<
"Unknown override character encoding \"" << encoding
1089 <<
"\". Using Auto instead." << endl;
1090 mSelectEncodingAction->setCurrentItem( 0 );
1091 mOverrideEncoding = TQString();
1099 void KMReaderWin::setPrintFont(
const TQFont& font )
1102 mCSSHelper->setPrintFont( font );
1108 if ( mOverrideEncoding.isEmpty() || mOverrideEncoding ==
"Auto" )
1111 return KMMsgBase::codecForName( mOverrideEncoding.latin1() );
1115 void KMReaderWin::slotSetEncoding()
1117 if ( mSelectEncodingAction->currentItem() == 0 )
1118 mOverrideEncoding = TQString();
1120 mOverrideEncoding = KGlobal::charsets()->encodingForName( mSelectEncodingAction->currentText() );
1125 void KMReaderWin::readGlobalOverrideCodec()
1128 if ( GlobalSettings::self()->overrideCharacterEncoding() == mOldGlobalOverrideEncoding )
1132 mOldGlobalOverrideEncoding = GlobalSettings::self()->overrideCharacterEncoding();
1138 mSerNumOfOriginalMessage = serNumOfOriginalMessage;
1139 mNodeIdOffset = nodeIdOffset;
1146 kdDebug(5006) <<
"(" << aMsg->getMsgSerNum() <<
", last " << mLastSerNum <<
") " << aMsg->
subject() <<
" "
1147 << aMsg->fromStrip() <<
", readyToShow " << (aMsg->
readyToShow()) << endl;
1151 if ( aMsg && aMsg->getMsgSerNum() != mLastSerNum && !updateOnly ){
1152 mLevelQuote = GlobalSettings::self()->collapseQuoteLevelSpin()-1;
1153 mShowRawToltecMail = !GlobalSettings::self()->showToltecReplacementText();
1154 clearBodyPartMementos();
1159 bool complete =
true;
1162 (aMsg->getMsgSerNum() != mLastSerNum) &&
1167 if (!force && aMsg && mLastSerNum != 0 && aMsg->getMsgSerNum() == mLastSerNum)
1174 aMsg->attach(
this );
1179 mDelayedMarkTimer.stop();
1183 mWaitingForSerNum = 0;
1186 mLastSerNum = aMsg->getMsgSerNum();
1203 mViewer->setDNDEnabled(
false );
1205 mViewer->setDNDEnabled(
true );
1215 mUpdateReaderWinTimer.stop();
1218 else if (mUpdateReaderWinTimer.isActive())
1219 mUpdateReaderWinTimer.changeInterval( delay );
1221 mUpdateReaderWinTimer.start( 0,
true );
1224 if ( aMsg && (aMsg->isUnread() || aMsg->isNew()) && GlobalSettings::self()->delayedMarkAsRead() ) {
1225 if ( GlobalSettings::self()->delayedMarkTime() != 0 )
1226 mDelayedMarkTimer.start( GlobalSettings::self()->delayedMarkTime() * 1000, true );
1235 mUpdateReaderWinTimer.stop();
1237 mDelayedMarkTimer.stop();
1239 mWaitingForSerNum = 0;
1244 static const char *
const kmailChanges[] = {
1247 static const int numKMailChanges =
1248 sizeof kmailChanges /
sizeof *kmailChanges;
1254 static const char *
const kmailNewFeatures[] = {
1255 I18N_NOOP(
"Full namespace support for IMAP"),
1256 I18N_NOOP(
"Offline mode"),
1257 I18N_NOOP(
"Sieve script management and editing"),
1258 I18N_NOOP(
"Account specific filtering"),
1259 I18N_NOOP(
"Filtering of incoming mail for online IMAP accounts"),
1260 I18N_NOOP(
"Online IMAP folders can be used when filtering into folders"),
1261 I18N_NOOP(
"Automatically delete older mails on POP servers")
1263 static const int numKMailNewFeatures =
1264 sizeof kmailNewFeatures /
sizeof *kmailNewFeatures;
1272 for (
int i = 0 ; i < numKMailChanges ; ++i )
1273 str += kmailChanges[i];
1274 for (
int i = 0 ; i < numKMailNewFeatures ; ++i )
1275 str += kmailNewFeatures[i];
1277 return md5.base64Digest();
1283 mMsgDisplay =
false;
1286 TQString location = locate(
"data",
"kmail/about/main.html");
1287 TQString content = KPIM::kFileToString(location);
1288 content = content.arg( locate(
"data",
"libkdepim/about/kde_infopage.css" ) );
1289 if ( kapp->reverseLayout() )
1290 content = content.arg(
"@import \"%1\";" ).arg( locate(
"data",
"libkdepim/about/kde_infopage_rtl.css" ) );
1292 content = content.arg(
"" );
1294 mViewer->begin(KURL( location ));
1296 TQString fontSize = TQString::number(
pointsToPixel( mCSSHelper->bodyFont().pointSize() ) );
1297 TQString appTitle = i18n(
"KMail");
1298 TQString catchPhrase =
"";
1299 TQString quickDescription = i18n(
"The email client for the K Desktop Environment.");
1300 mViewer->write(content.arg(fontSize).arg(appTitle).arg(catchPhrase).arg(quickDescription).arg(info));
1307 i18n(
"<h2 style='margin-top: 0px;'>Retrieving Folder Contents</h2><p>Please wait . . .</p> " );
1315 i18n(
"<h2 style='margin-top: 0px;'>Offline</h2><p>KMail is currently in offline mode. "
1316 "Click <a href=\"kmail:goOnline\">here</a> to go online . . .</p> " );
1326 i18n(
"%1: KMail version; %2: help:// URL; %3: homepage URL; "
1327 "%4: prior KMail version; %5: prior KDE version; "
1328 "%6: generated list of new features; "
1329 "%7: First-time user text (only shown on first start); "
1330 "%8: generated list of important changes; "
1331 "--- end of comment ---",
1332 "<h2 style='margin-top: 0px;'>Welcome to KMail %1</h2><p>KMail is the email client for the K "
1333 "Desktop Environment. It is designed to be fully compatible with "
1334 "Internet mailing standards including MIME, SMTP, POP3 and IMAP."
1336 "<ul><li>KMail has many powerful features which are described in the "
1337 "<a href=\"%2\">documentation</a></li>\n"
1338 "<li>The <a href=\"%3\">KMail homepage</A> offers information about "
1339 "new versions of KMail</li></ul>\n"
1341 "<p>Some of the new features in this release of KMail include "
1342 "(compared to KMail %4, which is part of KDE %5):</p>\n"
1345 "<p>We hope that you will enjoy KMail.</p>\n"
1346 "<p>Thank you,</p>\n"
1347 "<p style='margin-bottom: 0px'> The KMail Team</p>")
1349 .arg(
"help:/kmail/index.html")
1350 .arg(
"http://kontact.kde.org/kmail/")
1351 .arg(
"1.8").arg(
"3.4");
1353 TQString featureItems;
1354 for (
int i = 0 ; i < numKMailNewFeatures ; i++ )
1355 featureItems += i18n(
"<li>%1</li>\n").arg( i18n( kmailNewFeatures[i] ) );
1357 info = info.arg( featureItems );
1359 if( kmkernel->firstStart() ) {
1360 info = info.arg( i18n(
"<p>Please take a moment to fill in the KMail "
1361 "configuration panel at Settings->Configure "
1363 "You need to create at least a default identity and "
1364 "an incoming as well as outgoing mail account."
1367 info = info.arg( TQString() );
1370 if ( ( numKMailChanges > 1 ) || ( numKMailChanges == 1 && strlen(kmailChanges[0]) > 0 ) ) {
1371 TQString changesText =
1372 i18n(
"<p><span style='font-size:125%; font-weight:bold;'>"
1373 "Important changes</span> (compared to KMail %1):</p>\n")
1375 changesText +=
"<ul>\n";
1376 for (
int i = 0 ; i < numKMailChanges ; i++ )
1377 changesText += i18n(
"<li>%1</li>\n").arg( i18n( kmailChanges[i] ) );
1378 changesText +=
"</ul>\n";
1379 info = info.arg( changesText );
1382 info = info.arg(
"");
1397 if (!mMsgDisplay)
return;
1406 if ( mShowColorbar )
1415 mMimePartTree->hide();
1416 mMimePartTree->clear();
1417 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
1418 htmlWriter()->write( mCSSHelper->htmlHead( isFixedFont() ) +
"</body></html>" );
1422 if (mSavedRelativePosition)
1424 TQScrollView * scrollview =
static_cast<TQScrollView *
>(mViewer->widget());
1425 scrollview->setContentsPos( 0,
1426 tqRound( scrollview->contentsHeight() * mSavedRelativePosition ) );
1427 mSavedRelativePosition = 0;
1434 const TQPaintDeviceMetrics pdm(mViewer->view());
1436 return (pointSize * pdm.logicalDpiY() + 36) / 72;
1441 if ( mMimeTreeMode == 2 ||
1442 ( mMimeTreeMode == 1 && !isPlainTextTopLevel ) )
1443 mMimePartTree->show();
1446 KConfigGroup reader( KMKernel::config(),
"Reader" );
1447 saveSplitterSizes( reader );
1448 mMimePartTree->hide();
1455 mMimePartTree->clear();
1457 ( msg->type() == DwMime::kTypeText
1458 && msg->subtype() == DwMime::kSubtypePlain ) );
1465 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
1466 htmlWriter()->queue( mCSSHelper->htmlHead( isFixedFont() ) );
1477 if( mColorBar->isNeutral() )
1483 TQTimer::singleShot( 1, TQT_TQOBJECT(
this), TQT_SLOT(injectAttachments()) );
1486 static bool message_was_saved_decrypted_before(
const KMMessage * msg ) {
1490 return msg->
msgId().stripWhiteSpace().startsWith(
"<DecryptedMsg." );
1496 KMMessagePart msgPart;
1497 TQCString subtype, contDisp;
1502 aMsg->setIsBeingParsed(
true );
1504 if ( mRootNode && !mRootNode->processed() )
1506 kdWarning() <<
"The root node is not yet processed! Danger!\n";
1510 mRootNode = partNode::fromMessage( aMsg,
this );
1511 const TQCString mainCntTypeStr = mRootNode->typeString() +
'/' + mRootNode->subTypeString();
1513 TQString cntDesc = aMsg->
subject();
1514 if( cntDesc.isEmpty() )
1515 cntDesc = i18n(
"( body part )");
1516 KIO::filesize_t cntSize = aMsg->
msgSize();
1524 mRootNode->fillMimePartTree( 0,
1531 partNode* vCardNode = mRootNode->findType( DwMime::kTypeText, DwMime::kSubtypeXVCard );
1532 bool hasVCard =
false;
1536 KABC::VCardConverter t;
1537 #if defined(KABC_VCARD_ENCODING_FIX)
1538 const TQByteArray vcard = vCardNode->msgPart().bodyDecodedBinary();
1539 if ( !t.parseVCardsRaw( vcard.data() ).empty() ) {
1541 const TQString vcard = vCardNode->msgPart().bodyToUnicode(
overrideCodec() );
1542 if ( !t.parseVCards( vcard ).empty() ) {
1549 if ( !mRootNode || !mRootNode->isToltecMessage() || mShowRawToltecMail ) {
1554 ObjectTreeParser otp(
this );
1555 otp.setAllowAsync(
true );
1556 otp.setShowRawToltecMail( mShowRawToltecMail );
1557 otp.parseObjectTree( mRootNode );
1561 KMMsgEncryptionState encryptionState = mRootNode->overallEncryptionState();
1562 KMMsgSignatureState signatureState = mRootNode->overallSignatureState();
1571 if ( signatureState != KMMsgNotSigned ||
1576 bool emitReplaceMsgByUnencryptedVersion =
false;
1577 const KConfigGroup reader( KMKernel::config(),
"Reader" );
1578 if ( reader.readBoolEntry(
"store-displayed-messages-unencrypted",
false ) ) {
1593 kdDebug(5006) <<
"\n\n\nKMReaderWin::parseMsg() - special post-encryption handling:\n1." << endl;
1594 kdDebug(5006) <<
"(aMsg == msg) = " << (aMsg ==
message()) << endl;
1595 kdDebug(5006) <<
"aMsg->parent() && aMsg->parent() != kmkernel->outboxFolder() = " << (aMsg->parent() && aMsg->parent() != kmkernel->outboxFolder()) << endl;
1596 kdDebug(5006) <<
"message_was_saved_decrypted_before( aMsg ) = " << message_was_saved_decrypted_before( aMsg ) << endl;
1597 kdDebug(5006) <<
"this->decryptMessage() = " <<
decryptMessage() << endl;
1598 kdDebug(5006) <<
"otp.hasPendingAsyncJobs() = " << otp.hasPendingAsyncJobs() << endl;
1599 kdDebug(5006) <<
" (KMMsgFullyEncrypted == encryptionState) = " << (KMMsgFullyEncrypted == encryptionState) << endl;
1600 kdDebug(5006) <<
"|| (KMMsgPartiallyEncrypted == encryptionState) = " << (KMMsgPartiallyEncrypted == encryptionState) << endl;
1605 && ( aMsg->parent() && aMsg->parent() != kmkernel->outboxFolder() )
1607 && !message_was_saved_decrypted_before( aMsg )
1611 && !otp.hasPendingAsyncJobs()
1613 && ( (KMMsgFullyEncrypted == encryptionState)
1614 || (KMMsgPartiallyEncrypted == encryptionState) ) ) {
1616 kdDebug(5006) <<
"KMReaderWin - calling objectTreeToDecryptedMsg()" << endl;
1618 NewByteArray decryptedData;
1620 objectTreeToDecryptedMsg( mRootNode, decryptedData, *aMsg );
1622 decryptedData.appendNULL();
1623 TQCString resultString( decryptedData.data() );
1624 kdDebug(5006) <<
"KMReaderWin - resulting data:" << resultString << endl;
1626 if( !resultString.isEmpty() ) {
1627 kdDebug(5006) <<
"KMReaderWin - composing unencrypted message" << endl;
1629 aMsg->
setBody( resultString );
1631 unencryptedMessage->setParent( 0 );
1640 kdDebug(5006) <<
"KMReaderWin - attach unencrypted message to aMsg" << endl;
1642 emitReplaceMsgByUnencryptedVersion =
true;
1648 const int rootNodeCntType = mRootNode ? mRootNode->type() : DwMime::kTypeText;
1649 const int rootNodeCntSubtype = mRootNode ? mRootNode->subType() : DwMime::kSubtypePlain;
1654 if( emitReplaceMsgByUnencryptedVersion ) {
1655 kdDebug(5006) <<
"KMReaderWin - invoce saving in decrypted form:" << endl;
1658 kdDebug(5006) <<
"KMReaderWin - finished parsing and displaying of message." << endl;
1660 rootNodeCntSubtype == DwMime::kSubtypePlain );
1663 aMsg->setIsBeingParsed(
false );
1670 kdFatal( !headerStyle(), 5006 )
1671 <<
"trying to writeMsgHeader() without a header style set!" << endl;
1673 <<
"trying to writeMsgHeader() without a header strategy set!" << endl;
1676 href = vCardNode->asHREF(
"body" );
1678 return headerStyle()->format( aMsg,
headerStrategy(), href, mPrinting, topLevel );
1687 TQString fileName = aMsgPart->fileName();
1688 if( fileName.isEmpty() )
1689 fileName = aMsgPart->name();
1692 TQString fname =
createTempDir( TQString::number( aPartNum ) );
1693 if ( fname.isEmpty() )
1697 int slashPos = fileName.findRev(
'/' );
1698 if( -1 != slashPos )
1699 fileName = fileName.mid( slashPos + 1 );
1700 if( fileName.isEmpty() )
1701 fileName =
"unnamed";
1702 fname +=
"/" + fileName;
1704 TQByteArray data = aMsgPart->bodyDecodedBinary();
1705 size_t size = data.size();
1706 if ( aMsgPart->type() == DwMime::kTypeText && size) {
1710 if( !KPIM::kBytesToFile( data.data(), size, fname,
false,
false, false ) )
1713 mTempFiles.append( fname );
1716 ::chmod( TQFile::encodeName( fname ), S_IRUSR );
1723 KTempFile *tempFile =
new KTempFile( TQString(),
"." + param );
1724 tempFile->setAutoDelete(
true );
1725 TQString fname = tempFile->name();
1728 if( ::access( TQFile::encodeName( fname ), W_OK ) != 0 )
1730 if( ::mkdir( TQFile::encodeName( fname ), 0 ) != 0
1731 || ::chmod( TQFile::encodeName( fname ), S_IRWXU ) != 0 )
1734 assert( !fname.isNull() );
1736 mTempDirs.append( fname );
1743 #if defined(KABC_VCARD_ENCODING_FIX)
1744 const TQByteArray vCard = msgPart->bodyDecodedBinary();
1746 const TQString vCard = msgPart->bodyToUnicode(
overrideCodec() );
1748 VCardViewer *vcv =
new VCardViewer(
this, vCard,
"vCardDialog" );
1756 mViewer->view()->print();
1763 if (aUrl.isEmpty())
return -1;
1764 if (!aUrl.isLocalFile())
return -1;
1766 TQString path = aUrl.path();
1767 uint right = path.findRev(
'/');
1768 uint left = path.findRev(
'.', right);
1771 int res = path.mid(left + 1, right - left - 1).toInt(&ok);
1772 return (ok) ? res : -1;
1777 void KMReaderWin::resizeEvent(TQResizeEvent *)
1779 if( !mResizeTimer.isActive() )
1785 mResizeTimer.start( 100,
true );
1791 void KMReaderWin::slotDelayedResize()
1793 mSplitter->setGeometry(0, 0, width(), height());
1798 void KMReaderWin::slotTouchMessage()
1807 serNums.append(
message()->getMsgSerNum() );
1808 KMCommand *command =
new KMSeStatusCommand( KMMsgStatusRead, serNums );
1812 if ( mNoMDNsWhenEncrypted &&
1813 message()->encryptionState() != KMMsgNotEncrypted &&
1814 message()->encryptionState() != KMMsgEncryptionStateUnknown )
1826 if ( !kmkernel->msgSender()->send( receipt ) )
1827 KMessageBox::error(
this, i18n(
"Could not send MDN.") );
1839 bool foundSMIMEData(
const TQString aUrl,
1840 TQString& displayName,
1844 static TQString showCertMan(
"showCertificate#");
1848 int i1 = aUrl.find( showCertMan );
1850 i1 += showCertMan.length();
1851 int i2 = aUrl.find(
" ### ", i1);
1854 displayName = aUrl.mid( i1, i2-i1 );
1856 i2 = aUrl.find(
" ### ", i1);
1859 libName = aUrl.mid( i1, i2-i1 );
1862 keyId = aUrl.mid( i2 );
1878 return !keyId.isEmpty();
1885 const KURL url(aUrl);
1887 if ( url.protocol() ==
"kmail" || url.protocol() ==
"x-kmail" || url.protocol() ==
"attachment"
1888 || (url.protocol().isEmpty() && url.path().isEmpty()) ) {
1889 mViewer->setDNDEnabled(
false );
1891 mViewer->setDNDEnabled(
true );
1894 if ( aUrl.stripWhiteSpace().isEmpty() ) {
1895 KPIM::BroadcastStatus::instance()->reset();
1896 mHoveredUrl = KURL();
1897 mLastClickImagePath = TQString();
1903 const TQString msg = URLHandlerManager::instance()->statusBarMessage( url,
this );
1905 kdWarning( msg.isEmpty(), 5006 ) <<
"KMReaderWin::slotUrlOn(): Unhandled URL hover!" << endl;
1906 KPIM::BroadcastStatus::instance()->setTransienStatusMsg( msg );
1915 if ( URLHandlerManager::instance()->handleClick( aUrl,
this ) )
1918 kdWarning( 5006 ) <<
"KMReaderWin::slotOpenUrl(): Unhandled URL click!" << endl;
1925 const KURL url( aUrl );
1928 if ( url.protocol() ==
"mailto" ) {
1929 mCopyURLAction->setText( i18n(
"Copy Email Address" ) );
1931 mCopyURLAction->setText( i18n(
"Copy Link Address" ) );
1934 if ( URLHandlerManager::instance()->handleContextMenuRequest( url, aPos,
this ) )
1938 kdWarning( 5006 ) <<
"KMReaderWin::slotUrlPopup(): Unhandled URL right-click!" << endl;
1939 emitPopupMenu( url, aPos );
1945 static bool hasParentDivWithId(
const DOM::Node &start,
const TQString &
id )
1947 if ( start.isNull() )
1950 if ( start.nodeName().string() ==
"div" ) {
1951 for (
unsigned int i = 0; i < start.attributes().length(); i++ ) {
1952 if ( start.attributes().item( i ).nodeName().string() ==
"id" &&
1953 start.attributes().item( i ).nodeValue().string() == id )
1958 if ( !start.parentNode().isNull() )
1959 return hasParentDivWithId( start.parentNode(), id );
1964 void KMReaderWin::showAttachmentPopup(
int id,
const TQString & name,
const TQPoint & p )
1967 mAtmCurrentName = name;
1968 KPopupMenu *menu =
new KPopupMenu();
1969 menu->insertItem(SmallIcon(
"fileopen"),i18n(
"to open",
"Open"), 1);
1970 menu->insertItem(i18n(
"Open With..."), 2);
1971 menu->insertItem(i18n(
"to view something",
"View"), 3);
1972 menu->insertItem(SmallIcon(
"filesaveas"),i18n(
"Save As..."), 4);
1973 menu->insertItem(SmallIcon(
"editcopy"), i18n(
"Copy"), 9 );
1974 const bool canChange =
message()->parent() ? !
message()->parent()->isReadOnly() :
false;
1975 if ( GlobalSettings::self()->allowAttachmentEditing() && canChange )
1976 menu->insertItem(SmallIcon(
"edit"), i18n(
"Edit Attachment"), 8 );
1977 if ( GlobalSettings::self()->allowAttachmentDeletion() && canChange )
1978 menu->insertItem(SmallIcon(
"editdelete"), i18n(
"Delete Attachment"), 7 );
1979 if ( name.endsWith(
".xia",
false ) &&
1980 Kleo::CryptoBackendFactory::instance()->protocol(
"Chiasmus" ) )
1981 menu->insertItem( i18n(
"Decrypt With Chiasmus..." ), 6 );
1982 menu->insertItem(i18n(
"Properties"), 5);
1984 const bool attachmentInHeader = hasParentDivWithId( mViewer->nodeUnderMouse(),
"attachmentInjectionPoint" );
1985 const bool hasScrollbar = mViewer->view()->verticalScrollBar()->isVisible();
1986 if ( attachmentInHeader && hasScrollbar ) {
1987 menu->insertItem( i18n(
"Scroll To"), 10 );
1990 connect(menu, TQT_SIGNAL(activated(
int)), TQT_TQOBJECT(
this), TQT_SLOT(slotHandleAttachment(
int)));
2002 if( style().isA(
"KeramikStyle") )
2003 frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth ) - 1;
2005 frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth );
2006 if ( frameWidth < 0 )
2008 if ( frameWidth != mBox->lineWidth() )
2009 mBox->setLineWidth( frameWidth );
2020 void KMReaderWin::slotHandleAttachment(
int choice )
2023 partNode* node = mRootNode ? mRootNode->findId( mAtmCurrent ) : 0;
2024 if ( mAtmCurrentName.isEmpty() && node )
2025 mAtmCurrentName = tempFileUrlFromPartNode( node ).path();
2027 KMHandleAttachmentCommand* command =
new KMHandleAttachmentCommand(
2028 node,
message(), mAtmCurrent, mAtmCurrentName,
2029 KMHandleAttachmentCommand::AttachmentAction( choice ), 0,
this );
2030 connect( command, TQT_SIGNAL( showAttachment(
int,
const TQString& ) ),
2031 TQT_TQOBJECT(
this), TQT_SLOT(
slotAtmView(
int,
const TQString& ) ) );
2033 }
else if ( choice == 7 ) {
2034 slotDeleteAttachment( node );
2035 }
else if ( choice == 8 ) {
2036 slotEditAttachment( node );
2037 }
else if ( choice == 9 ) {
2038 if ( !node )
return;
2040 KURL url = tempFileUrlFromPartNode( node );
2041 if (!url.isValid() )
return;
2043 KURLDrag* drag =
new KURLDrag( urls,
this );
2044 TQApplication::clipboard()->setData( drag, TQClipboard::Clipboard );
2045 }
else if ( choice == 10 ) {
2053 mViewer->findText();
2059 mViewer->findTextNext();
2065 mUseFixedFont = !mUseFixedFont;
2074 kapp->clipboard()->setText( mViewer->selectedText() );
2081 assert(aMsgPart!=0);
2083 msg->fromString(aMsgPart->bodyDecoded());
2087 msg->setParent(
message()->parent() );
2088 msg->setUID(
message()->UID());
2090 KMReaderMainWin *win =
new KMReaderMainWin();
2099 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
2100 htmlWriter()->write( mCSSHelper->htmlHead( isFixedFont() ) );
2103 ObjectTreeParser otp(
this, 0,
true );
2104 otp.parseObjectTree( node );
2113 const TQString& aFileName,
const TQString& pname )
2116 if (kasciistricmp(aMsgPart->typeStr(),
"message")==0) {
2119 assert(aMsgPart!=0);
2120 msg->fromString(aMsgPart->bodyDecoded());
2121 mMainWindow->setCaption(msg->
subject());
2123 setAutoDelete(
true);
2124 }
else if (kasciistricmp(aMsgPart->typeStr(),
"text")==0) {
2125 if (kasciistricmp(aMsgPart->subtypeStr(),
"x-vcard") == 0) {
2129 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
2130 htmlWriter()->queue( mCSSHelper->htmlHead( isFixedFont() ) );
2132 if (aHTML && (kasciistricmp(aMsgPart->subtypeStr(),
"html")==0)) {
2137 const TQCString str = aMsgPart->bodyDecoded();
2138 ObjectTreeParser otp(
this );
2139 otp.writeBodyStr( str,
2145 mMainWindow->setCaption(i18n(
"View Attachment: %1").arg(pname));
2146 }
else if (kasciistricmp(aMsgPart->typeStr(),
"image")==0 ||
2147 (kasciistricmp(aMsgPart->typeStr(),
"application")==0 &&
2148 kasciistricmp(aMsgPart->subtypeStr(),
"postscript")==0))
2150 if (aFileName.isEmpty())
return;
2152 TQImageIO *iio =
new TQImageIO();
2153 iio->setFileName(aFileName);
2155 TQImage img = iio->image();
2156 TQRect desk = KGlobalSettings::desktopGeometry(mMainWindow);
2159 if( img.width() < 50 )
2161 else if( img.width()+20 < desk.width() )
2162 width = img.width()+20;
2164 width = desk.width();
2165 if( img.height() < 50 )
2167 else if( img.height()+20 < desk.height() )
2168 height = img.height()+20;
2170 height = desk.height();
2171 mMainWindow->resize( width, height );
2174 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
2175 htmlWriter()->write( mCSSHelper->htmlHead( isFixedFont() ) );
2177 KURL::encode_string( aFileName ) +
2178 "\" border=\"0\">\n"
2179 "</body></html>\n" );
2181 setCaption( i18n(
"View Attachment: %1").arg( pname ) );
2185 htmlWriter()->begin( mCSSHelper->cssDefinitions( isFixedFont() ) );
2186 htmlWriter()->queue( mCSSHelper->htmlHead( isFixedFont() ) );
2189 TQString str = aMsgPart->bodyDecoded();
2192 if( str.length() < (unsigned) aMsgPart->decodedSize() ) {
2193 str.prepend( i18n(
"[KMail: Attachment contains binary data. Trying to show first character.]",
2194 "[KMail: Attachment contains binary data. Trying to show first %n characters.]",
2195 str.length()) + TQChar(
'\n') );
2197 htmlWriter()->queue( TQStyleSheet::escape( str ) );
2201 mMainWindow->setCaption(i18n(
"View Attachment: %1").arg(pname));
2210 partNode* node = mRootNode ? mRootNode->findId(
id ) : 0;
2213 mAtmCurrentName = name;
2214 if ( mAtmCurrentName.isEmpty() )
2215 mAtmCurrentName = tempFileUrlFromPartNode( node ).path();
2217 KMMessagePart& msgPart = node->msgPart();
2218 TQString pname = msgPart.fileName();
2219 if (pname.isEmpty()) pname=msgPart.name();
2220 if (pname.isEmpty()) pname=msgPart.contentDescription();
2221 if (pname.isEmpty()) pname=
"unnamed";
2223 if (kasciistricmp(msgPart.typeStr(),
"message")==0) {
2225 }
else if ((kasciistricmp(msgPart.typeStr(),
"text")==0) &&
2226 (kasciistricmp(msgPart.subtypeStr(),
"x-vcard")==0)) {
2229 KMReaderMainWin *win =
new KMReaderMainWin(&msgPart,
htmlMail(),
2237 void KMReaderWin::openAttachment(
int id,
const TQString & name )
2239 mAtmCurrentName = name;
2242 TQString str, pname, cmd, fileName;
2244 partNode* node = mRootNode ? mRootNode->findId(
id ) : 0;
2246 kdWarning(5006) <<
"KMReaderWin::openAttachment - could not find node " <<
id << endl;
2249 if ( mAtmCurrentName.isEmpty() )
2250 mAtmCurrentName = tempFileUrlFromPartNode( node ).path();
2252 KMMessagePart& msgPart = node->msgPart();
2253 if (kasciistricmp(msgPart.typeStr(),
"message")==0)
2259 TQCString contentTypeStr( msgPart.typeStr() +
'/' + msgPart.subtypeStr() );
2260 KPIM::kAsciiToLower( contentTypeStr.data() );
2262 if ( qstrcmp( contentTypeStr,
"text/x-vcard" ) == 0 ) {
2268 KMimeType::Ptr mimetype;
2270 mimetype = KMimeType::mimeType( TQString::fromLatin1( contentTypeStr ) );
2271 if ( mimetype->name() ==
"application/octet-stream" ) {
2273 mimetype = KMimeType::findByPath( name, 0,
true );
2275 if ( ( mimetype->name() ==
"application/octet-stream" )
2276 && msgPart.isComplete() ) {
2279 mimetype = KMimeType::findByFileContent( name );
2282 KService::Ptr offer =
2283 KServiceTypeProfile::preferredService( mimetype->name(),
"Application" );
2286 TQString filenameText = msgPart.fileName();
2287 if ( filenameText.isEmpty() )
2288 filenameText = msgPart.name();
2290 open_text = i18n(
"&Open with '%1'").arg( offer->name() );
2292 open_text = i18n(
"&Open With...");
2294 const TQString text = i18n(
"Open attachment '%1'?\n"
2295 "Note that opening an attachment may compromise "
2296 "your system's security.")
2297 .arg( filenameText );
2298 const int choice = KMessageBox::questionYesNoCancel(
this, text,
2299 i18n(
"Open Attachment?"), KStdGuiItem::saveAs(), open_text,
2300 TQString::fromLatin1(
"askSave") + mimetype->name() );
2302 if( choice == KMessageBox::Yes ) {
2304 KMHandleAttachmentCommand* command =
new KMHandleAttachmentCommand( node,
2305 message(), mAtmCurrent, mAtmCurrentName, KMHandleAttachmentCommand::Save,
2307 connect( command, TQT_SIGNAL( showAttachment(
int,
const TQString& ) ),
2308 TQT_TQOBJECT(
this), TQT_SLOT(
slotAtmView(
int,
const TQString& ) ) );
2311 else if( choice == KMessageBox::No ) {
2312 KMHandleAttachmentCommand::AttachmentAction action = ( offer ?
2313 KMHandleAttachmentCommand::Open : KMHandleAttachmentCommand::OpenWith );
2315 KMHandleAttachmentCommand* command =
new KMHandleAttachmentCommand( node,
2316 message(), mAtmCurrent, mAtmCurrentName, action, offer,
this );
2317 connect( command, TQT_SIGNAL( showAttachment(
int,
const TQString& ) ),
2318 TQT_TQOBJECT(
this), TQT_SLOT(
slotAtmView(
int,
const TQString& ) ) );
2321 kdDebug(5006) <<
"Canceled opening attachment" << endl;
2328 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, -10);
2333 void KMReaderWin::slotScrollDown()
2335 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, 10);
2338 bool KMReaderWin::atBottom()
const
2340 const TQScrollView *view =
static_cast<const TQScrollView *
>(mViewer->widget());
2341 return view->contentsY() + view->visibleHeight() >= view->contentsHeight();
2345 void KMReaderWin::slotJumpDown()
2347 TQScrollView *view =
static_cast<TQScrollView *
>(mViewer->widget());
2348 int offs = (view->clipper()->height() < 30) ? view->clipper()->height() : 30;
2349 view->scrollBy( 0, view->clipper()->height() - offs );
2353 void KMReaderWin::slotScrollPrior()
2355 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, -(
int)(height()*0.8));
2360 void KMReaderWin::slotScrollNext()
2362 static_cast<TQScrollView *
>(mViewer->widget())->scrollBy(0, (
int)(height()*0.8));
2366 void KMReaderWin::slotDocumentChanged()
2373 void KMReaderWin::slotTextSelected(
bool)
2375 TQString temp = mViewer->selectedText();
2376 kapp->clipboard()->setText(temp);
2382 mViewer->selectAll();
2388 TQString temp = mViewer->selectedText();
2394 void KMReaderWin::slotDocumentDone()
2401 void KMReaderWin::setHtmlOverride(
bool override)
2403 mHtmlOverride =
override;
2410 void KMReaderWin::setHtmlLoadExtOverride(
bool override)
2412 mHtmlLoadExtOverride =
override;
2421 return ((mHtmlMail && !mHtmlOverride) || (!mHtmlMail && mHtmlOverride));
2428 return ((mHtmlLoadExternal && !mHtmlLoadExtOverride) ||
2429 (!mHtmlLoadExternal && mHtmlLoadExtOverride));
2436 const TQScrollView * scrollview =
static_cast<TQScrollView *
>( mViewer->widget() );
2437 mSavedRelativePosition =
2438 static_cast<float>( scrollview->contentsY() ) / scrollview->contentsHeight();
2447 setMsg( msg, force,
true );
2455 KMFolder*& folder = aFolder ? *aFolder : tmpFolder;
2464 message = folder->
getMsg( index );
2466 kdWarning(5006) <<
"Attempt to reference invalid serial number " << mLastSerNum <<
"\n" << endl;
2475 void KMReaderWin::slotUrlClicked()
2477 KMMainWidget *mainWidget =
dynamic_cast<KMMainWidget*
>(mMainWindow);
2480 identity =
message()->parent()->identity();
2483 KMCommand *command =
new KMUrlClickedCommand( mClickedUrl, identity,
this,
2484 false, mainWidget );
2489 void KMReaderWin::slotMailtoCompose()
2491 KMCommand *command =
new KMMailtoComposeCommand( mClickedUrl,
message() );
2496 void KMReaderWin::slotMailtoForward()
2498 KMCommand *command =
new KMMailtoForwardCommand( mMainWindow, mClickedUrl,
2504 void KMReaderWin::slotMailtoAddAddrBook()
2506 KMCommand *command =
new KMMailtoAddAddrBookCommand( mClickedUrl,
2512 void KMReaderWin::slotMailtoOpenAddrBook()
2514 KMCommand *command =
new KMMailtoOpenAddrBookCommand( mClickedUrl,
2524 KMCommand *command =
2525 new KMUrlCopyCommand( mClickedUrl,
2526 dynamic_cast<KMMainWidget*>( mMainWindow ) );
2533 if ( !url.isEmpty() )
2535 KMCommand *command =
new KMUrlOpenCommand( mClickedUrl,
this );
2540 void KMReaderWin::slotAddBookmarks()
2542 KMCommand *command =
new KMAddBookmarksCommand( mClickedUrl,
this );
2549 KMCommand *command =
new KMUrlSaveCommand( mClickedUrl, mMainWindow );
2556 KMCommand *command =
new KMMailtoReplyCommand( mMainWindow, mClickedUrl,
2563 return mRootNode ? mRootNode->findId(
msgPartFromUrl( url ) ) : 0 ;
2566 partNode * KMReaderWin::partNodeForId(
int id ) {
2567 return mRootNode ? mRootNode->findId(
id ) : 0 ;
2571 KURL KMReaderWin::tempFileUrlFromPartNode(
const partNode * node )
2573 if (!node)
return KURL();
2574 TQStringList::const_iterator it = mTempFiles.begin();
2575 TQStringList::const_iterator end = mTempFiles.end();
2577 while ( it != end ) {
2578 TQString path = *it;
2580 uint right = path.findRev(
'/');
2581 uint left = path.findRev(
'.', right);
2584 int res = path.mid(left + 1, right - left - 1).toInt(&ok);
2585 if ( res == node->nodeId() )
2586 return KURL( path );
2592 void KMReaderWin::slotSaveAttachments()
2595 KMSaveAttachmentsCommand *saveCommand =
new KMSaveAttachmentsCommand( mMainWindow,
2597 saveCommand->start();
2601 void KMReaderWin::saveAttachment(
const KURL &tempFileName )
2604 mAtmCurrentName = mClickedUrl.path();
2605 slotHandleAttachment( KMHandleAttachmentCommand::Save );
2609 void KMReaderWin::slotSaveMsg()
2611 KMSaveMsgCommand *saveCommand =
new KMSaveMsgCommand( mMainWindow,
message() );
2613 if (saveCommand->url().isEmpty())
2616 saveCommand->start();
2621 KMCommand *command =
new KMIMChatCommand( mClickedUrl,
message() );
2626 static TQString linkForNode(
const DOM::Node &node )
2629 if ( node.isNull() )
2632 const DOM::NamedNodeMap attributes = node.attributes();
2633 if ( !attributes.isNull() ) {
2634 const DOM::Node href = attributes.getNamedItem( DOM::DOMString(
"href" ) );
2635 if ( !href.isNull() ) {
2636 return href.nodeValue().string();
2639 if ( !node.parentNode().isNull() ) {
2640 return linkForNode( node.parentNode() );
2644 }
catch ( DOM::DOMException &e ) {
2645 kdWarning(5006) <<
"Got an exception when trying to determine link under cursor!" << endl;
2653 if ( e->type() == TQEvent::MouseButtonPress ) {
2654 TQMouseEvent* me = TQT_TQMOUSEEVENT(e);
2655 if ( me->button() == Qt::LeftButton && ( me->state() & ShiftButton ) ) {
2657 URLHandlerManager::instance()->handleShiftClick( mHoveredUrl,
this );
2661 if ( me->button() == Qt::LeftButton ) {
2664 const DOM::Node nodeUnderMouse = mViewer->nodeUnderMouse();
2665 if ( !nodeUnderMouse.isNull() ) {
2666 const DOM::NamedNodeMap attributes = nodeUnderMouse.attributes();
2667 if ( !attributes.isNull() ) {
2668 const DOM::Node src = attributes.getNamedItem( DOM::DOMString(
"src" ) );
2669 if ( !src.isNull() ) {
2670 imagePath = src.nodeValue().string();
2675 mCanStartDrag = URLHandlerManager::instance()->willHandleDrag( mHoveredUrl, imagePath,
this );
2676 mLastClickPosition = me->pos();
2677 mLastClickImagePath = imagePath;
2681 if ( e->type() == TQEvent::MouseButtonRelease ) {
2682 mCanStartDrag =
false;
2685 if ( e->type() == TQEvent::MouseMove ) {
2686 TQMouseEvent* me = TQT_TQMOUSEEVENT( e );
2690 slotUrlOn( linkForNode( mViewer->nodeUnderMouse() ) );
2692 if ( ( mLastClickPosition - me->pos() ).manhattanLength() > KGlobalSettings::dndEventDelay() ) {
2693 if ( mCanStartDrag && ( !( mHoveredUrl.isEmpty() && mLastClickImagePath.isEmpty() ) ) ) {
2694 if ( URLHandlerManager::instance()->handleDrag( mHoveredUrl, mLastClickImagePath,
this ) ) {
2695 mCanStartDrag =
false;
2701 TQMouseEvent mouseEvent( TQEvent::MouseButtonRelease, me->pos(), Qt::NoButton, Qt::NoButton );
2702 TQT_TQOBJECT( mViewer->view() )->
eventFilter( mViewer->view()->viewport(),
2716 Q_ASSERT( msg && nodeId );
2718 if ( mSerNumOfOriginalMessage != 0 ) {
2722 if ( folder && index != -1 )
2723 *msg = folder->
getMsg( index );
2726 kdWarning( 5006 ) <<
"Unable to find the original message, aborting attachment deletion!" << endl;
2730 *nodeId = node->nodeId() + mNodeIdOffset;
2733 *nodeId = node->nodeId();
2738 void KMReaderWin::slotDeleteAttachment(partNode * node)
2740 if ( KMessageBox::warningContinueCancel(
this,
2741 i18n(
"Deleting an attachment might invalidate any digital signature on this message."),
2742 i18n(
"Delete Attachment"), KStdGuiItem::del(),
"DeleteAttachmentSignatureWarning" )
2743 != KMessageBox::Continue ) {
2750 if ( msg && nodeId != -1 ) {
2751 KMDeleteAttachmentCommand* command =
new KMDeleteAttachmentCommand( nodeId, msg,
this );
2753 connect( command, TQT_SIGNAL( completed( KMCommand * ) ),
2755 connect( command, TQT_SIGNAL( completed( KMCommand * ) ),
2764 connect( headers, TQT_SIGNAL( msgAddedToListView( TQListViewItem* ) ),
2765 TQT_TQOBJECT(
this), TQT_SLOT( msgAdded( TQListViewItem* ) ) );
2769 if ( mSerNumOfOriginalMessage != 0 &&
message() ) {
2775 void KMReaderWin::msgAdded( TQListViewItem *item )
2782 headers->setCurrentItem( item );
2783 headers->clearSelection();
2790 disconnect( headers, TQT_SIGNAL( msgAddedToListView( TQListViewItem* ) ),
2791 TQT_TQOBJECT(
this), TQT_SLOT( msgAdded( TQListViewItem* ) ) );
2794 void KMReaderWin::slotEditAttachment(partNode * node)
2796 if ( KMessageBox::warningContinueCancel(
this,
2797 i18n(
"Modifying an attachment might invalidate any digital signature on this message."),
2798 i18n(
"Edit Attachment"), KGuiItem( i18n(
"Edit"),
"edit" ),
"EditAttachmentSignatureWarning" )
2799 != KMessageBox::Continue ) {
2806 if ( msg && nodeId != -1 ) {
2807 KMEditAttachmentCommand* command =
new KMEditAttachmentCommand( nodeId, msg,
this );
2814 KMail::CSSHelper* KMReaderWin::cssHelper()
2821 if ( !GlobalSettings::self()->alwaysDecrypt() )
2822 return mDecrytMessageOverwrite;
2828 DOM::Document doc = mViewer->htmlDocument();
2831 mViewer->gotoAnchor( TQString::fromLatin1(
"att%1" ).arg( node->nodeId() ) );
2834 const partNode *root = node->topLevelParent();
2835 for (
int i = 0; i <= root->totalChildCount() + 1; i++ ) {
2836 DOM::Element attachmentDiv = doc.getElementById( TQString(
"attachmentDiv%1" ).arg( i + 1 ) );
2837 if ( !attachmentDiv.isNull() )
2838 attachmentDiv.removeAttribute(
"style" );
2842 if ( node->isDisplayedHidden() )
2848 DOM::Element attachmentDiv = doc.getElementById( TQString(
"attachmentDiv%1" ).arg( node->nodeId() ) );
2849 if ( attachmentDiv.isNull() ) {
2850 kdWarning( 5006 ) <<
"Could not find attachment div for attachment " << node->nodeId() << endl;
2854 attachmentDiv.setAttribute(
"style", TQString(
"border:2px solid %1" )
2855 .arg( cssHelper()->pgpWarnColor().name() ) );
2859 doc.updateRendering();
2862 void KMReaderWin::injectAttachments()
2866 DOM::Document doc = mViewer->htmlDocument();
2867 DOM::Element injectionPoint = doc.getElementById(
"attachmentInjectionPoint" );
2868 if ( injectionPoint.isNull() )
2871 TQString imgpath( locate(
"data",
"kmail/pics/") );
2872 TQString visibility;
2875 if( !showAttachmentQuicklist() ) {
2876 urlHandle.append(
"kmail:showAttachmentQuicklist" );
2877 imgSrc.append(
"attachmentQuicklistClosed.png" );
2879 urlHandle.append(
"kmail:hideAttachmentQuicklist" );
2880 imgSrc.append(
"attachmentQuicklistOpened.png" );
2883 TQString html = renderAttachments( mRootNode, TQApplication::palette().active().background() );
2884 if ( html.isEmpty() )
2888 if ( headerStyle() == HeaderStyle::fancy() ) {
2889 link +=
"<div style=\"text-align: left;\"><a href=\"" + urlHandle +
"\"><img src=\"" +
2890 imgpath + imgSrc +
"\"/></a></div>";
2891 html.prepend( link );
2892 html.prepend( TQString::fromLatin1(
"<div style=\"float:left;\">%1 </div>" ).
2893 arg( i18n(
"Attachments:" ) ) );
2895 link +=
"<div style=\"text-align: right;\"><a href=\"" + urlHandle +
"\"><img src=\"" +
2896 imgpath + imgSrc +
"\"/></a></div>";
2897 html.prepend( link );
2900 assert( injectionPoint.tagName() ==
"div" );
2901 static_cast<DOM::HTMLElement
>( injectionPoint ).setInnerHTML( html );
2904 static TQColor nextColor(
const TQColor & c )
2907 c.hsv( &h, &s, &v );
2908 return TQColor( (h + 50) % 360, TQMAX(s, 64), v, TQColor::Hsv );
2911 TQString KMReaderWin::renderAttachments(partNode * node,
const TQColor &bgColor )
2917 if ( node->firstChild() ) {
2918 TQString subHtml = renderAttachments( node->firstChild(), nextColor( bgColor ) );
2919 if ( !subHtml.isEmpty() ) {
2921 TQString visibility;
2922 if ( !showAttachmentQuicklist() ) {
2923 visibility.append(
"display:none;" );
2927 if ( node != mRootNode || headerStyle() != HeaderStyle::enterprise() )
2928 margin =
"padding:2px; margin:2px; ";
2929 TQString align =
"left";
2930 if ( headerStyle() == HeaderStyle::enterprise() )
2932 if ( node->msgPart().typeStr().lower() ==
"message" || node == mRootNode )
2933 html += TQString::fromLatin1(
"<div style=\"background:%1; %2"
2934 "vertical-align:middle; float:%3; %4\">").arg( bgColor.name() ).arg( margin )
2935 .arg( align ).arg( visibility );
2937 if ( node->msgPart().typeStr().lower() ==
"message" || node == mRootNode )
2941 partNode::AttachmentDisplayInfo info = node->attachmentDisplayInfo();
2942 if ( info.displayInHeader ) {
2943 html +=
"<div style=\"float:left;\">";
2944 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() );
2946 TQString href = node->asHREF(
"header" );
2947 html += TQString::fromLatin1(
"<a href=\"" ) + href +
2948 TQString::fromLatin1(
"\">" );
2949 html +=
"<img style=\"vertical-align:middle;\" src=\"" + info.icon +
"\"/> ";
2950 if ( headerStyle() == HeaderStyle::enterprise() ) {
2951 TQFont bodyFont = mCSSHelper->bodyFont( isFixedFont() );
2952 TQFontMetrics fm( bodyFont );
2953 html += KStringHandler::rPixelSqueeze( info.label, fm, 140 );
2954 }
else if ( headerStyle() == HeaderStyle::fancy() ) {
2955 TQFont bodyFont = mCSSHelper->bodyFont( isFixedFont() );
2956 TQFontMetrics fm( bodyFont );
2957 html += KStringHandler::rPixelSqueeze( info.label, fm, 640 );
2961 html +=
"</a></span></div> ";
2965 html += renderAttachments( node->nextSibling(), nextColor ( bgColor ) );
2969 using namespace KMail::Interface;
2971 void KMReaderWin::setBodyPartMemento(
const partNode * node,
const TQCString & which,
BodyPartMemento * memento )
2973 const TQCString index = node->path() +
':' + which.lower();
2975 const std::map<TQCString,BodyPartMemento*>::iterator it = mBodyPartMementoMap.lower_bound( index );
2976 if ( it != mBodyPartMementoMap.end() && it->first == index ) {
2978 if ( memento && memento == it->second )
2984 it->second = memento;
2987 mBodyPartMementoMap.erase( it );
2992 mBodyPartMementoMap.insert( it, std::make_pair( index, memento ) );
3000 BodyPartMemento * KMReaderWin::bodyPartMemento(
const partNode * node,
const TQCString & which )
const
3002 const TQCString index = node->path() +
':' + which.lower();
3003 const std::map<TQCString,BodyPartMemento*>::const_iterator it = mBodyPartMementoMap.find( index );
3004 if ( it == mBodyPartMementoMap.end() ) {
3018 void KMReaderWin::clearBodyPartMementos()
3020 for ( std::map<TQCString,BodyPartMemento*>::const_iterator it = mBodyPartMementoMap.begin(), end = mBodyPartMementoMap.end() ; it != end ; ++it )
3025 detach_and_delete( it->second,
this );
3027 mBodyPartMementoMap.clear();
3030 #include "kmreaderwin.moc"