7#include "mimetreemodel.h"
8#include "messageviewer_debug.h"
10#include <MimeTreeParser/NodeHelper>
11#include <MimeTreeParser/Util>
13#include <KMime/Content>
14#include <KMime/Message>
17#include <KLocalizedString>
21#include <QMimeDatabase>
22#include <QTemporaryDir>
25using namespace MessageViewer;
30 MimeTreeModelPrivate() =
default;
32 ~MimeTreeModelPrivate()
43 QString descriptionForContent(KMime::Content *content)
45 auto const message =
dynamic_cast<KMime::Message *
>(content);
46 if (message && message->subject(
false)) {
47 return message->subject(
false)->asUnicodeString();
54 const QString desc = ct->asUnicodeString();
59 return i18n(
"body part");
62 QString mimeTypeForContent(KMime::Content *content)
70 QString typeForContent(KMime::Content *content)
74 const auto mimeType = m_mimeDb.mimeTypeForName(contentMimeType);
76 return contentMimeType;
84 QString sizeOfContent(KMime::Content *content)
92 QIcon iconForContent(KMime::Content *content)
95 auto iconName = MimeTreeParser::Util::iconNameForMimetype(QLatin1StringView(ct->mimeType()));
98 if (!
mimeType.isValid() ||
mimeType.name() == QLatin1StringView(
"application/octet-stream")) {
99 const QString
name = descriptionForContent(content);
100 mimeType = MimeTreeParser::Util::mimetype(name);
105 }
else if (!iconName.isEmpty() && iconName != QLatin1StringView(
"unknown")) {
117 QList<QTemporaryDir *> tempDirs;
118 KMime::Content *root =
nullptr;
119 QMimeDatabase m_mimeDb;
122MimeTreeModel::MimeTreeModel(
QObject *parent)
124 , d(new MimeTreeModelPrivate)
128MimeTreeModel::~MimeTreeModel() =
default;
132 if (d->root != root) {
140KMime::Content *MimeTreeModel::root()
145QModelIndex MimeTreeModel::index(
int row,
int column,
const QModelIndex &parent)
const
147 if (!parent.isValid()) {
154 auto parentContent =
static_cast<KMime::Content *
>(parent.internalPointer());
155 if (!parentContent || parentContent->contents().count() <= row || row < 0) {
158 KMime::Content *content = parentContent->
contents().at(row);
164 if (!index.isValid()) {
167 auto currentContent =
static_cast<KMime::Content *
>(index.internalPointer());
168 if (!currentContent) {
172 KMime::ContentIndex currentIndex = d->root->indexForContent(currentContent);
177 KMime::Content *parentContent = d->root->content(currentIndex);
180 row = currentIndex.
up() - 1;
186int MimeTreeModel::rowCount(
const QModelIndex &parent)
const
191 if (!parent.isValid()) {
194 auto parentContent =
static_cast<KMime::Content *
>(parent.internalPointer());
196 return parentContent->
contents().count();
201int MimeTreeModel::columnCount(
const QModelIndex &parent)
const
207QVariant MimeTreeModel::data(
const QModelIndex &index,
int role)
const
209 auto content =
static_cast<KMime::Content *
>(index.internalPointer());
219 switch (index.column()) {
221 return d->descriptionForContent(content);
223 return d->typeForContent(content);
225 return d->sizeOfContent(content);
229 return d->iconForContent(content);
231 if (role == ContentIndexRole) {
234 if (role == ContentRole) {
237 if (role == MimeTypeRole) {
238 return d->mimeTypeForContent(content);
240 if (role == MainBodyPartRole) {
241 auto topLevelMsg =
dynamic_cast<KMime::Message *
>(d->root);
245 return topLevelMsg->mainBodyPart() == content;
247 if (role == AlternativeBodyPartRole) {
248 auto topLevelMsg =
dynamic_cast<KMime::Message *
>(d->root);
257QVariant MimeTreeModel::headerData(
int section,
Qt::Orientation orientation,
int role)
const
262 return i18n(
"Description");
272QMimeData *MimeTreeModel::mimeData(
const QModelIndexList &indexes)
const
275 for (
const QModelIndex &index : indexes) {
277 if (index.column() != 0) {
280 auto content =
static_cast<KMime::Content *
>(index.internalPointer());
285 if (data.isEmpty()) {
289 auto tempDir =
new QTemporaryDir;
290 d->tempDirs.
append(tempDir);
291 const QString fileName = tempDir->path() + QLatin1Char(
'/') + d->descriptionForContent(content);
294 qCWarning(MESSAGEVIEWER_LOG) <<
"Cannot write attachment:" << f.errorString();
297 if (f.write(data) != data.length()) {
298 qCWarning(MESSAGEVIEWER_LOG) <<
"Failed to write all data to file!";
304 qCDebug(MESSAGEVIEWER_LOG) <<
" temporary file " << url;
308 auto mimeData =
new QMimeData;
309 mimeData->setUrls(urls);
313Qt::ItemFlags MimeTreeModel::flags(
const QModelIndex &index)
const
319QStringList MimeTreeModel::mimeTypes()
const
321 const QStringList types = {QStringLiteral(
"text/uri-list")};
325#include "moc_mimetreemodel.cpp"
const Headers::ContentType * contentType() const
QByteArray decodedContent() const
QList< Content * > contents()
const Headers::ContentDescription * contentDescription() const
A model representing the mime part tree of a message.
static QString fileName(const KMime::Content *node)
Returns a usable filename for a node, that can be the filename from the content disposition header,...
QString i18n(const char *text, const TYPE &arg...)
KCALUTILS_EXPORT QString mimeType()
KIOCORE_EXPORT QString convertSize(KIO::filesize_t size)
QString name(const QVariant &location)
QModelIndex createIndex(int row, int column, const void *ptr) const const
virtual Qt::ItemFlags flags(const QModelIndex &index) const const
QByteArray & append(QByteArrayView data)
bool isEmpty() const const
qsizetype size() const const
QIcon fromTheme(const QString &name)
void append(QList< T > &&value)
QObject * parent() const const
QString fromLatin1(QByteArrayView str)
bool isEmpty() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QUrl fromLocalFile(const QString &localFile)
QVariant fromValue(T &&value)