7#include "job/maintextjob.h"
9#include "contentjobbase_p.h"
10#include "job/multipartjob.h"
11#include "job/singlepartjob.h"
12#include "part/globalpart.h"
13#include "part/textpart.h"
14#include "utils/util.h"
16#include <QStringEncoder>
18#include "messagecomposer_debug.h"
19#include <KLocalizedString>
21#include <KMime/Content>
25class MessageComposer::MainTextJobPrivate :
public ContentJobBasePrivate
28 MainTextJobPrivate(MainTextJob *qq)
29 : ContentJobBasePrivate(qq)
33 [[nodiscard]]
bool chooseSourcePlainText();
34 [[nodiscard]]
bool chooseCharsetAndEncode();
35 [[nodiscard]]
bool chooseCharset();
36 [[nodiscard]]
bool encodeTexts();
37 [[nodiscard]] SinglepartJob *createPlainTextJob();
38 [[nodiscard]] SinglepartJob *createHtmlJob();
39 [[nodiscard]] SinglepartJob *createImageJob(
const QSharedPointer<KPIMTextEdit::EmbeddedImage> &image);
41 TextPart *textPart =
nullptr;
42 QByteArray chosenCharset;
43 QString sourcePlainText;
44 QByteArray encodedPlainText;
45 QByteArray encodedHtml;
47 Q_DECLARE_PUBLIC(MainTextJob)
50bool MainTextJobPrivate::chooseSourcePlainText()
54 if (textPart->isWordWrappingEnabled()) {
55 sourcePlainText = textPart->wrappedPlainText();
56 if (sourcePlainText.isEmpty() && !textPart->cleanPlainText().isEmpty()) {
57 q->setError(JobBase::BugError);
58 q->setErrorText(
i18n(
"Asked to use word wrapping, but not given wrapped plain text."));
62 sourcePlainText = textPart->cleanPlainText();
63 if (sourcePlainText.isEmpty() && !textPart->wrappedPlainText().isEmpty()) {
64 q->setError(JobBase::BugError);
65 q->setErrorText(
i18n(
"Asked not to use word wrapping, but not given clean plain text."));
72bool MainTextJobPrivate::chooseCharsetAndEncode()
77 QString toTry = sourcePlainText;
78 if (textPart->isHtmlUsed()) {
79 toTry = textPart->cleanHtml();
81 chosenCharset =
"utf-8";
85bool MainTextJobPrivate::encodeTexts()
88 QStringEncoder codec(chosenCharset.constData());
89 if (!codec.isValid()) {
90 qCCritical(MESSAGECOMPOSER_LOG) <<
"Could not get text codec for charset" << chosenCharset;
91 q->setError(JobBase::BugError);
95 encodedPlainText = codec.encode(sourcePlainText);
96 if (!textPart->cleanHtml().isEmpty()) {
97 encodedHtml = codec.encode(textPart->cleanHtml());
99 qCDebug(MESSAGECOMPOSER_LOG) <<
"Done.";
105 auto cjob =
new SinglepartJob;
107 cjob->contentType()->setCharset(chosenCharset);
108 cjob->setData(encodedPlainText);
115 auto cjob =
new SinglepartJob;
117 cjob->contentType()->setCharset(chosenCharset);
118 const QByteArray data = KPIMTextEdit::RichTextComposerImages::imageNamesToContentIds(encodedHtml, textPart->embeddedImages());
124SinglepartJob *MainTextJobPrivate::createImageJob(
const QSharedPointer<KPIMTextEdit::EmbeddedImage> &image)
129 auto cjob =
new SinglepartJob;
130 cjob->contentType()->setMimeType(
"image/png");
131 cjob->contentType()->setName(image->imageName);
132 cjob->contentTransferEncoding()->setEncoding(KMime::Headers::CEbase64);
133 cjob->setDataIsEncoded(
true);
134 cjob->contentID()->setIdentifier(image->contentID.toLatin1());
135 qCDebug(MESSAGECOMPOSER_LOG) <<
"cid" << cjob->contentID()->identifier();
136 cjob->setData(image->image);
140MainTextJob::MainTextJob(
TextPart *textPart, QObject *parent)
144 d->textPart = textPart;
147MainTextJob::~MainTextJob() =
default;
149TextPart *MainTextJob::textPart()
const
151 Q_D(
const MainTextJob);
155void MainTextJob::setTextPart(
TextPart *part)
161void MainTextJob::doStart()
164 Q_ASSERT(d->textPart);
167 if (!d->chooseSourcePlainText()) {
175 if (!d->chooseCharsetAndEncode()) {
183 SinglepartJob *plainJob = d->createPlainTextJob();
184 if (d->encodedHtml.isEmpty()) {
185 qCDebug(MESSAGECOMPOSER_LOG) <<
"Making text/plain";
189 auto alternativeJob =
new MultipartJob;
190 alternativeJob->setMultipartSubtype(
"alternative");
191 alternativeJob->appendSubjob(plainJob);
192 alternativeJob->appendSubjob(d->createHtmlJob());
193 if (!d->textPart->hasEmbeddedImages()) {
194 qCDebug(MESSAGECOMPOSER_LOG) <<
"Have no images. Making multipart/alternative.";
198 qCDebug(MESSAGECOMPOSER_LOG) <<
"Have related images. Making multipart/related.";
200 auto multipartJob =
new MultipartJob;
201 multipartJob->setMultipartSubtype(
"related");
202 multipartJob->appendSubjob(alternativeJob);
203 const auto embeddedImages = d->textPart->embeddedImages();
204 for (
const QSharedPointer<KPIMTextEdit::EmbeddedImage> &image : embeddedImages) {
205 multipartJob->appendSubjob(d->createImageJob(image));
213void MainTextJob::process()
217 Q_ASSERT(d->subjobContents.count() == 1);
218 d->resultContent = d->subjobContents.constFirst();
222#include "moc_maintextjob.cpp"
The ContentJobBase class.
virtual void doStart()
Reimplement to do additional stuff before processing children, such as adding more subjobs.
bool appendSubjob(ContentJobBase *job)
This is meant to be used instead of KCompositeJob::addSubjob(), making it possible to add subjobs fro...
QString i18n(const char *text, const TYPE &arg...)
Simple interface that both EncryptJob and SignEncryptJob implement so the composer can extract some e...
QString fromLatin1(QByteArrayView str)