22#include <klocalizedstring.h>
24#include <kmime/kmime_message.h>
30#include <QTextDocument>
35#define X_NOTES_UID_HEADER "X-Akonotes-UID"
36#define X_NOTES_LASTMODIFIED_HEADER "X-Akonotes-LastModified"
37#define X_NOTES_CLASSIFICATION_HEADER "X-Akonotes-Classification"
38#define X_NOTES_CUSTOM_HEADER "X-Akonotes-Custom"
40#define CLASSIFICATION_PUBLIC "Public"
41#define CLASSIFICATION_PRIVATE "Private"
42#define CLASSIFICATION_CONFIDENTIAL "Confidential"
44#define X_NOTES_URL_HEADER "X-Akonotes-Url"
45#define X_NOTES_LABEL_HEADER "X-Akonotes-Label"
46#define X_NOTES_CONTENTTYPE_HEADER "X-Akonotes-Type"
47#define CONTENT_TYPE_CUSTOM "custom"
48#define CONTENT_TYPE_ATTACHMENT "attachment"
50#define ENCODING "utf-8"
52class Attachment::AttachmentPrivate
55 AttachmentPrivate(
const QUrl&
url,
const QString&
mimetype )
60 AttachmentPrivate(
const QByteArray&
data,
const QString&
mimetype )
65 AttachmentPrivate(
const AttachmentPrivate &other )
77: d_ptr( new
Attachment::AttachmentPrivate( url, mimetype ) )
82: d_ptr( new
Attachment::AttachmentPrivate( data, mimetype ) )
87: d_ptr(new AttachmentPrivate(*other.d_func()) )
92Attachment::~Attachment()
97bool Attachment::operator==(
const Attachment &a )
const
99 const Q_D( Attachment );
100 if ( d->mUrl.isEmpty() ) {
101 return d->mUrl == a.d_func()->mUrl &&
102 d->mMimetype == a.d_func()->mMimetype &&
103 d->mLabel == a.d_func()->mLabel;
105 return d->mData == a.d_func()->mData &&
106 d->mMimetype == a.d_func()->mMimetype &&
107 d->mLabel == a.d_func()->mLabel;
110void Attachment::operator=(
const Attachment &a )
145class NoteMessageWrapper::NoteMessageWrapperPrivate
148 NoteMessageWrapperPrivate()
149 : classification( Public )
153 NoteMessageWrapperPrivate(
const KMime::Message::Ptr &msg )
154 : classification( Public ),
155 textFormat( Qt::PlainText )
157 readMimeMessage(msg);
160 void readMimeMessage(
const KMime::Message::Ptr &msg );
162 KMime::Content* createCustomPart()
const;
163 void parseCustomPart( KMime::Content * );
165 KMime::Content* createAttachmentPart(
const Attachment & )
const;
166 void parseAttachmentPart( KMime::Content * );
172 KDateTime creationDate;
173 KDateTime lastModifiedDate;
174 QMap< QString, QString > custom;
175 QList<Attachment> attachments;
176 Classification classification;
177 Qt::TextFormat textFormat;
180void NoteMessageWrapper::NoteMessageWrapperPrivate::readMimeMessage(
const KMime::Message::Ptr& msg)
183 kWarning() <<
"Empty message";
186 title = msg->subject(
true )->asUnicodeString();
187 text = msg->mainBodyPart()->decodedText(
true );
188 if ( msg->from(
false ) )
189 from = msg->from(
false )->asUnicodeString();
190 creationDate = msg->date(
true )->dateTime();
191 if ( msg->mainBodyPart()->contentType(
false ) && msg->mainBodyPart()->contentType()->mimeType() ==
"text/html" ) {
192 textFormat = Qt::RichText;
195 if (KMime::Headers::Base *lastmod = msg->headerByType(X_NOTES_LASTMODIFIED_HEADER)) {
196 const QByteArray &s = lastmod->asUnicodeString().toLatin1();
197 const char *cursor = s.constData();
198 if (!KMime::HeaderParsing::parseDateTime( cursor, cursor + s.length(), lastModifiedDate)) {
199 kWarning() <<
"failed to parse lastModifiedDate";
203 if (KMime::Headers::Base *uidHeader = msg->headerByType(X_NOTES_UID_HEADER)) {
204 uid = uidHeader->asUnicodeString();
207 if (KMime::Headers::Base *classificationHeader = msg->headerByType(X_NOTES_CLASSIFICATION_HEADER)) {
208 const QString &c = classificationHeader->asUnicodeString();
209 if ( c == CLASSIFICATION_PRIVATE ) {
210 classification = Private;
211 }
else if ( c == CLASSIFICATION_CONFIDENTIAL ) {
212 classification = Confidential;
216 const KMime::Content::List list = msg->contents();
217 Q_FOREACH(KMime::Content *c, msg->contents()) {
218 if (KMime::Headers::Base *typeHeader = c->headerByType(X_NOTES_CONTENTTYPE_HEADER)) {
219 const QString &type = typeHeader->asUnicodeString();
220 if ( type == CONTENT_TYPE_CUSTOM ) {
222 }
else if ( type == CONTENT_TYPE_ATTACHMENT ) {
223 parseAttachmentPart(c);
225 qWarning() <<
"unknown type " << type;
231QDomDocument createXMLDocument()
233 QDomDocument document;
234 QString p =
"version=\"1.0\" encoding=\"UTF-8\"";
235 document.appendChild(document.createProcessingInstruction(
"xml", p ) );
239QDomDocument loadDocument(KMime::Content *part)
242 int errorLine, errorColumn;
243 QDomDocument document;
244 bool ok = document.setContent( part->body(), &errorMsg, &errorLine, &errorColumn );
246 kWarning() << part->body();
247 qWarning(
"Error loading document: %s, line %d, column %d", qPrintable( errorMsg ), errorLine, errorColumn );
248 return QDomDocument();
253KMime::Content* NoteMessageWrapper::NoteMessageWrapperPrivate::createCustomPart()
const
255 KMime::Content* content =
new KMime::Content();
256 content->appendHeader(
new KMime::Headers::Generic( X_NOTES_CONTENTTYPE_HEADER, content, CONTENT_TYPE_CUSTOM, ENCODING ) );
257 QDomDocument document = createXMLDocument();
258 QDomElement element = document.createElement(
"custom" );
259 element.setAttribute(
"version",
"1.0" );
260 for ( QMap <QString, QString >::const_iterator it = custom.begin(); it != custom.end(); ++it ) {
261 QDomElement e = element.ownerDocument().createElement( it.key() );
262 QDomText t = element.ownerDocument().createTextNode( it.value() );
264 element.appendChild( e );
265 document.appendChild( element );
267 content->setBody( document.toString().toLatin1() );
271void NoteMessageWrapper::NoteMessageWrapperPrivate::parseCustomPart( KMime::Content* part )
273 QDomDocument document = loadDocument( part );
274 if (document.isNull()) {
277 QDomElement top = document.documentElement();
278 if ( top.tagName() !=
"custom" ) {
279 qWarning(
"XML error: Top tag was %s instead of the expected custom",
280 top.tagName().toLatin1().data() );
284 for ( QDomNode n = top.firstChild(); !n.isNull(); n = n.nextSibling() ) {
285 if ( n.isElement() ) {
286 QDomElement e = n.toElement();
287 custom.insert(e.tagName(), e.text());
289 kDebug() <<
"Node is not an element";
295KMime::Content* NoteMessageWrapper::NoteMessageWrapperPrivate::createAttachmentPart(
const Attachment &a )
const
297 KMime::Content* content =
new KMime::Content();
298 content->appendHeader(
new KMime::Headers::Generic( X_NOTES_CONTENTTYPE_HEADER, content, CONTENT_TYPE_ATTACHMENT, ENCODING ) );
299 if (a.url().isValid()) {
300 content->appendHeader(
new KMime::Headers::Generic( X_NOTES_URL_HEADER, content, a.url().toString().toLatin1(), ENCODING ) );
302 content->setBody( a.data() );
304 content->contentType()->setMimeType( a.mimetype().toLatin1() );
305 if (!a.label().isEmpty()) {
306 content->appendHeader(
new KMime::Headers::Generic( X_NOTES_LABEL_HEADER, content, a.label().toLatin1(), ENCODING ) );
308 content->contentTransferEncoding()->setEncoding( KMime::Headers::CEbase64 );
309 content->contentDisposition()->setDisposition( KMime::Headers::CDattachment );
310 content->contentDisposition()->setFilename(
"attachment" );
314void NoteMessageWrapper::NoteMessageWrapperPrivate::parseAttachmentPart( KMime::Content *part )
317 if ( KMime::Headers::Base *labelHeader = part->headerByType( X_NOTES_LABEL_HEADER ) ) {
318 label = labelHeader->asUnicodeString();
320 if ( KMime::Headers::Base *header = part->headerByType( X_NOTES_URL_HEADER ) ) {
321 Attachment attachment( QUrl( header->asUnicodeString() ), part->contentType()->mimeType() );
322 attachment.setLabel( label );
323 attachments.append(attachment);
325 Attachment attachment( part->decodedContent(), part->contentType()->mimeType() );
326 attachment.setLabel( label );
327 attachments.append(attachment);
331NoteMessageWrapper::NoteMessageWrapper()
332: d_ptr( new NoteMessageWrapperPrivate() )
336NoteMessageWrapper::NoteMessageWrapper(
const KMime::Message::Ptr &msg )
337: d_ptr( new NoteMessageWrapperPrivate(msg) )
341NoteMessageWrapper::~NoteMessageWrapper()
349 KMime::Message::Ptr msg = KMime::Message::Ptr(
new KMime::Message() );
351 QString
title = i18nc(
"The default name for new notes.",
"New Note" );
352 if ( !d->title.isEmpty() ) {
356 QString
text = QLatin1String(
" ");
357 if ( !d->text.isEmpty() ) {
361 KDateTime
creationDate = KDateTime::currentLocalDateTime();
362 if ( d->creationDate.isValid() ) {
367 if ( d->lastModifiedDate.isValid() ) {
372 if ( !d->uid.isEmpty() ) {
375 uid = QUuid::createUuid();
378 msg->subject(
true )->fromUnicodeString(
title, ENCODING );
380 msg->from(
true )->fromUnicodeString( d->from, ENCODING );
381 msg->mainBodyPart()->fromUnicodeString(
text );
382 msg->mainBodyPart()->contentType(
true )->setMimeType( d->textFormat == Qt::RichText ?
"text/html" :
"text/plain" );
383 msg->appendHeader(
new KMime::Headers::Generic(X_NOTES_LASTMODIFIED_HEADER, msg.get(),
lastModifiedDate.toString( KDateTime::RFCDateDay ).toLatin1(), ENCODING ) );
384 msg->appendHeader(
new KMime::Headers::Generic( X_NOTES_UID_HEADER, msg.get(),
uid, ENCODING ) );
386 QString
classification = QString::fromLatin1(CLASSIFICATION_PUBLIC);
387 switch ( d->classification ) {
392 classification = QString::fromLatin1(CLASSIFICATION_CONFIDENTIAL);
398 msg->appendHeader(
new KMime::Headers::Generic( X_NOTES_CLASSIFICATION_HEADER, msg.get(),
classification, ENCODING ) );
400 foreach (
const Attachment &a, d->attachments) {
401 msg->addContent( d->createAttachmentPart(a) );
404 if ( !d->custom.isEmpty() ) {
405 msg->addContent( d->createCustomPart() );
433 return d->classification;
445 return d->lastModifiedDate;
457 return d->creationDate;
488 d->textFormat = format;
500 return d->textFormat;
506 if ( d->textFormat == Qt::PlainText ) {
511 QRegExp rx( QLatin1String(
"<body[^>]*>(.*)</body>"), Qt::CaseInsensitive );
512 rx.indexIn( d->text );
513 QString body = rx.cap( 1 );
515 return Qt::escape( body.remove( QRegExp( QLatin1String(
"<[^>]*>") ) ).trimmed() );
521 return d->attachments;
530QString noteIconName()
532 return QString::fromLatin1(
"text-plain" );
535QString noteMimeType()
537 return QString::fromLatin1(
"text/x-vnd.akonadi.note" );
An attachment for a note.
QString label() const
Returns the label of the attachment.
QByteArray data() const
Returns the date for inline attachments.
QString mimetype() const
Returns the mimetype.
Attachment(const QUrl &url, const QString &mimetype)
Create an attachment referencing a url only.
void setLabel(const QString &label)
Sets the label to be presented to the user.
QUrl url() const
Returns the url for url-only attachments.
A convenience wrapper around KMime::Message::Ptr for notes.
QMap< QString, QString > & custom()
Returns a reference to the custom-value map.
void setText(const QString &text, Qt::TextFormat format=Qt::PlainText)
Set the text of the note.
QString from() const
Returns the origin (creator) of the note.
QList< Attachment > & attachments()
Returns a reference to the list of attachments of the note.
void setFrom(const QString &from)
Set the origin (creator) of the note (stored in the mime header) This is usually the application crea...
Qt::TextFormat textFormat() const
QString text() const
Returns the text of the note.
void setUid(const QString &uid)
Set the uid of the note.
KMime::MessagePtr message() const
Assemble a KMime message with the given values.
KDateTime creationDate() const
Returns the creation date of the note.
void setClassification(Classification)
Set the classification of the note.
void setLastModifiedDate(const KDateTime &lastModifiedDate)
Set the lastModified-date of the note.
void setCreationDate(const KDateTime &creationDate)
Set the creation date of the note (stored in the mime header)
QString title() const
Returns the title of the note.
Classification classification() const
Returns the classification of the note.
void setTitle(const QString &title)
Set the title of the note.
KDateTime lastModifiedDate() const
Returns the lastModified-date of the note.
QString toPlainText() const
QString uid() const
Returns the uid of the note.
FreeBusyManager::Singleton.