diff --git a/messageviewer/src/interfaces/bodypartformatter.h b/messageviewer/src/interfaces/bodypartformatter.h --- a/messageviewer/src/interfaces/bodypartformatter.h +++ b/messageviewer/src/interfaces/bodypartformatter.h @@ -35,18 +35,54 @@ #define __KMAIL_INTERFACE_BODYPARTFORMATTER_H__ #include +#include + +#include +#include namespace MessageViewer { -class HtmlWriter; namespace Interface { -class BodyPart; +class HtmlWriter; class BodyPartURLHandler; +class MessagePart +{ +public: + typedef QSharedPointer Ptr; + explicit MessagePart() + : mHtmlWriter(0) + , mPart(0) + { + } + + explicit MessagePart(const BodyPart &part) + : mHtmlWriter(0) + , mPart(&part) + { + + } + virtual ~MessagePart() {} + + virtual void html(bool decorate); + virtual QString text() const + { + return QString(); + } + +private: + HtmlWriter *htmlWriter(); + + HtmlWriter *mHtmlWriter; + const BodyPart *mPart; + + friend class BodyPartFormatter; +}; + class BodyPartFormatter { public: @@ -79,6 +115,17 @@ Q_UNUSED(asyncResultObserver); return format(part, writer); } + + virtual MessagePart::Ptr process(BodyPart &part) const + { + qDebug() << "should never happen tm"; + auto mp = MessagePart::Ptr(new MessagePart(part)); + const auto ret = format(&part,mp->htmlWriter()); + if (ret != Failed) { + return mp; + } + return MessagePart::Ptr(); + } }; /** diff --git a/messageviewer/src/viewer/bodypartformatter.cpp b/messageviewer/src/viewer/bodypartformatter.cpp --- a/messageviewer/src/viewer/bodypartformatter.cpp +++ b/messageviewer/src/viewer/bodypartformatter.cpp @@ -42,14 +42,28 @@ using namespace MessageViewer; +Interface::HtmlWriter* Interface::MessagePart::htmlWriter() +{ + if (!mHtmlWriter) { + mHtmlWriter = mPart->objectTreeParser()->htmlWriter(); + } + return mHtmlWriter; +} + +void Interface::MessagePart::html(bool decorate) +{ + static_cast(mHtmlWriter)->replay(); +} + + namespace { class AnyTypeBodyPartFormatter : public MessageViewer::Interface::BodyPartFormatter { static const AnyTypeBodyPartFormatter *self; public: - Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE + Result format(Interface::BodyPart *, Interface::HtmlWriter *) const Q_DECL_OVERRIDE { qCDebug(MESSAGEVIEWER_LOG) << "Acting as a Interface::BodyPartFormatter!"; return AsIcon; @@ -79,7 +93,7 @@ { static const ImageTypeBodyPartFormatter *self; public: - Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE + Result format(Interface::BodyPart *, Interface::HtmlWriter *) const Q_DECL_OVERRIDE { return AsIcon; } @@ -108,8 +122,8 @@ { static const MessageRfc822BodyPartFormatter *self; public: - MessagePart::Ptr process(Interface::BodyPart *) const; - MessageViewer::Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE; + Interface::MessagePart::Ptr process(Interface::BodyPart &) const Q_DECL_OVERRIDE; + MessageViewer::Interface::BodyPartFormatter::Result format(Interface::BodyPart *, Interface::HtmlWriter *) const Q_DECL_OVERRIDE; using MessageViewer::Interface::BodyPartFormatter::format; static const MessageViewer::Interface::BodyPartFormatter *create(); }; @@ -124,17 +138,18 @@ return self; } -MessagePart::Ptr MessageRfc822BodyPartFormatter::process(Interface::BodyPart *part) const +Interface::MessagePart::Ptr MessageRfc822BodyPartFormatter::process(Interface::BodyPart &part) const { - const KMime::Message::Ptr message = part->content()->bodyAsMessage(); - return MessagePart::Ptr(new EncapsulatedRfc822MessagePart(part->objectTreeParser(), part->content(), message)); + const KMime::Message::Ptr message = part.content()->bodyAsMessage(); + return MessagePart::Ptr(new EncapsulatedRfc822MessagePart(part.objectTreeParser(), part.content(), message)); } -MessageViewer::Interface::BodyPartFormatter::Result MessageRfc822BodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const +Interface::BodyPartFormatter::Result MessageRfc822BodyPartFormatter::format(Interface::BodyPart *part, Interface::HtmlWriter *writer) const { Q_UNUSED(writer) const ObjectTreeParser *otp = part->objectTreeParser(); - const MessagePart::Ptr mp = process(part); + const auto p = process(*part); + const auto mp = static_cast(p.data()); if (mp && !otp->attachmentStrategy()->inlineNestedMessages() && !otp->showOnlyOneMimePart()) { return Failed; } else { @@ -149,8 +164,8 @@ { \ static const subtype##BodyPartFormatter *self; \ public: \ - MessagePart::Ptr process(const Interface::BodyPart &part) const; \ - MessageViewer::Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE; \ + Interface::MessagePart::Ptr process(Interface::BodyPart &part) const Q_DECL_OVERRIDE; \ + MessageViewer::Interface::BodyPartFormatter::Result format(Interface::BodyPart *, Interface::HtmlWriter *) const Q_DECL_OVERRIDE; \ using MessageViewer::Interface::BodyPartFormatter::format; \ static const MessageViewer::Interface::BodyPartFormatter *create(); \ }; \ @@ -163,14 +178,15 @@ } \ return self; \ } \ - MessagePart::Ptr subtype##BodyPartFormatter::process(const Interface::BodyPart &part) const { \ + Interface::MessagePart::Ptr subtype##BodyPartFormatter::process(Interface::BodyPart &part) const { \ return part.objectTreeParser()->process##subtype##Subtype(part.content(), *part.processResult()); \ } \ \ - MessageViewer::Interface::BodyPartFormatter::Result subtype##BodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const { \ + MessageViewer::Interface::BodyPartFormatter::Result subtype##BodyPartFormatter::format(Interface::BodyPart *part, Interface::HtmlWriter *writer) const { \ Q_UNUSED(writer) \ - MessagePart::Ptr mp = process(*part);\ - if (!mp.isNull()) {\ + const auto p = process(*part);\ + const auto mp = static_cast(p.data());\ + if (mp) { \ mp->html(false);\ return Ok;\ }\ diff --git a/messageviewer/src/viewer/messagepart.h b/messageviewer/src/viewer/messagepart.h --- a/messageviewer/src/viewer/messagepart.h +++ b/messageviewer/src/viewer/messagepart.h @@ -22,6 +22,7 @@ #include "partmetadata.h" #include "nodehelper.h" +#include "interfaces/bodypartformatter.h" #include #include @@ -163,18 +164,18 @@ const QString &mMsg; }; -class MessagePart +class MessagePart : public Interface::MessagePart { public: typedef QSharedPointer Ptr; MessagePart(ObjectTreeParser *otp, const QString &text); virtual ~MessagePart(); - virtual QString text() const; + virtual QString text() const Q_DECL_OVERRIDE; void setText(const QString &text); - virtual void html(bool decorate); + virtual void html(bool decorate) Q_DECL_OVERRIDE; PartMetaData *partMetaData(); diff --git a/messageviewer/src/viewer/objecttreeparser.cpp b/messageviewer/src/viewer/objecttreeparser.cpp --- a/messageviewer/src/viewer/objecttreeparser.cpp +++ b/messageviewer/src/viewer/objecttreeparser.cpp @@ -333,40 +333,57 @@ subType = node->contentType()->subType(); } - // First, try if an external plugin can handle this MIME part - if (const Interface::BodyPartFormatter * formatter - = BodyPartFormatterFactory::instance()->createFor(mediaType, subType)) { + bool bRendered = false; + const auto sub = BodyPartFormatterFactory::instance()->subtypeRegistry(mediaType); + const auto end = sub.end(); + auto it = sub.find(subType); + if (it == end) { + it = sub.find("*"); + } + for (; it != end; ++it) { + const auto formatter = (*it).second; + if (!formatter) { + continue; + } PartNodeBodyPart part(this, &processResult, mTopLevelContent, node, mNodeHelper, codecFor(node)); // Set the default display strategy for this body part relying on the // identity of Interface::BodyPart::Display and AttachmentStrategy::Display part.setDefaultDisplay((Interface::BodyPart::Display) attachmentStrategy()->defaultDisplay(node)); mNodeHelper->setNodeDisplayedEmbedded(node, true); - AttachmentMarkBlock block(htmlWriter(), node); - QObject *asyncResultObserver = allowAsync() ? mSource->sourceObject() : 0; - const Interface::BodyPartFormatter::Result result = formatter->format(&part, htmlWriter(), asyncResultObserver); - switch (result) { - case Interface::BodyPartFormatter::AsIcon: - processResult.setNeverDisplayInline(true); - mNodeHelper->setNodeDisplayedEmbedded(node, false); - // fall through: - case Interface::BodyPartFormatter::Failed: - { - const auto mp = defaultHandling(node, processResult); - if (mp) { - mp->html(false); - } - break; + const auto result = formatter->process(part); + if (!result) { + continue; } - case Interface::BodyPartFormatter::Ok: - case Interface::BodyPartFormatter::NeedContent: - // FIXME: incomplete content handling - ; + + if (const auto mp = dynamic_cast(result.data())) { + AttachmentMarkBlock block(htmlWriter(), node); + mp->html(false); + bRendered = true; + break; + } else if (dynamic_cast(result.data())) { + QObject *asyncResultObserver = allowAsync() ? mSource->sourceObject() : 0; + const auto r = formatter->format(&part, htmlWriter(), asyncResultObserver); + if (r == Interface::BodyPartFormatter::AsIcon) { + //qDebug() << node << "asIcon"; + AttachmentMarkBlock block(htmlWriter(), node); + processResult.setNeverDisplayInline(true); + mNodeHelper->setNodeDisplayedEmbedded(node, false); + const auto mp = defaultHandling(node, processResult); + if (mp) { + mp->html(false); + } + bRendered = true; + break; + } + continue; + } else { + continue; } + } - // No external plugin can handle the MIME part, handle it internally - } else { + if (!bRendered) { qCCritical(MESSAGEVIEWER_LOG) << "THIS SHOULD NO LONGER HAPPEN:" << mediaType << '/' << subType; AttachmentMarkBlock block(htmlWriter(), node); const auto mp = defaultHandling(node, processResult);