Commit 646c0725 authored by Sandro Knauß's avatar Sandro Knauß

Split logic for detecting a valid mimeType

the basic logc into MimeTreeParser, the advanced in MessageViewer
parent 0f405bd7
......@@ -612,10 +612,10 @@ public:
if (mp->mAsIcon == MimeTreeParser::IconInline) {
iconPath = nodeHelper->writeNodeToTempFile(node);
} else {
iconPath = MessageViewer::Util::fileNameForContent(node, KIconLoader::Desktop);
iconPath = MessageViewer::Util::iconPathForContent(node, KIconLoader::Desktop);
if (iconPath.right(14) == QLatin1String("mime_empty.png")) {
nodeHelper->magicSetType(node);
iconPath = MessageViewer::Util::fileNameForContent(node, KIconLoader::Desktop);
iconPath = MessageViewer::Util::iconPathForContent(node, KIconLoader::Desktop);
}
}
block.setProperty("iconPath", QUrl::fromLocalFile(iconPath).url());
......
......@@ -22,113 +22,32 @@
#include "messageviewer_debug.h"
#include <MimeTreeParser/NodeHelper>
#include <MimeTreeParser/Util>
#include <KIconLoader>
#include <KMime/Content>
#include <QMimeDatabase>
QMimeType MessageViewer::Util::mimetype(const QString &name)
{
QMimeDatabase db;
// consider the filename if mimetype cannot be found by content-type
auto mimeTypes = db.mimeTypesForFileName(name);
foreach (const auto &mt, mimeTypes) {
if (mt.name() != QLatin1String("application/octet-stream")) {
return mt;
}
}
// consider the attachment's contents if neither the Content-Type header
// nor the filename give us a clue
return db.mimeTypeForFile(name);
}
QString MessageViewer::Util::fileNameForMimetype(const QString &mimeType, int iconSize,
QString MessageViewer::Util::iconPathForMimetype(const QString &mimeType, int iconSize,
const QString &fallbackFileName1,
const QString &fallbackFileName2)
{
QString fileName;
QString tMimeType = mimeType;
// convert non-registered types to registered types
if (mimeType == QLatin1String("application/x-vnd.kolab.contact")) {
tMimeType = QStringLiteral("text/x-vcard");
} else if (mimeType == QLatin1String("application/x-vnd.kolab.event")) {
tMimeType = QStringLiteral("application/x-vnd.akonadi.calendar.event");
} else if (mimeType == QLatin1String("application/x-vnd.kolab.task")) {
tMimeType = QStringLiteral("application/x-vnd.akonadi.calendar.todo");
} else if (mimeType == QLatin1String("application/x-vnd.kolab.journal")) {
tMimeType = QStringLiteral("application/x-vnd.akonadi.calendar.journal");
} else if (mimeType == QLatin1String("application/x-vnd.kolab.note")) {
tMimeType = QStringLiteral("application/x-vnd.akonadi.note");
} else if (mimeType == QLatin1String("image/jpg")) {
tMimeType = QStringLiteral("image/jpeg");
}
QMimeDatabase mimeDb;
auto mime = mimeDb.mimeTypeForName(tMimeType);
if (mime.isValid()) {
fileName = mime.iconName();
} else {
fileName = QStringLiteral("unknown");
if (!tMimeType.isEmpty()) {
qCWarning(MESSAGEVIEWER_LOG) << "unknown mimetype" << tMimeType;
}
}
//WorkAround for #199083
if (fileName == QLatin1String("text-vcard")) {
fileName = QStringLiteral("text-x-vcard");
}
if (fileName.isEmpty()) {
fileName = fallbackFileName1;
if (fileName.isEmpty()) {
fileName = fallbackFileName2;
}
if (!fileName.isEmpty()) {
fileName = mimeDb.mimeTypeForFile(QLatin1String("/tmp/") + fileName).iconName();
}
}
return IconNameCache::instance()->iconPath(fileName, iconSize);
return IconNameCache::instance()->iconPath(MimeTreeParser::Util::iconNameForMimetype(mimeType, fallbackFileName1, fallbackFileName2), iconSize);
}
QString MessageViewer::Util::fileNameForContent(KMime::Content *node, int size)
QString MessageViewer::Util::iconPathForContent(KMime::Content *node, int size)
{
if (!node) {
return QString();
}
QByteArray mimeType = node->contentType()->mimeType();
if (mimeType.isNull() || mimeType == "application/octet-stream") {
const QString mime = Util::mimetype(node->contentDisposition()->filename()).name();
mimeType = mime.toLatin1();
}
mimeType = mimeType.toLower();
return fileNameForMimetype(QLatin1String(mimeType), size, node->contentDisposition()->filename(),
node->contentType()->name());
return IconNameCache::instance()->iconPath(MimeTreeParser::Util::iconNameForContent(node), size);
}
MessageViewer::Util::AttachmentDisplayInfo MessageViewer::Util::attachmentDisplayInfo(KMime::Content *node)
{
AttachmentDisplayInfo info;
info.icon = fileNameForContent(node, KIconLoader::Small);
const QString name = node->contentType()->name();
info.label = name.isEmpty() ? MimeTreeParser::NodeHelper::fileName(node) : name;
if (info.label.isEmpty()) {
info.label = node->contentDescription()->asUnicodeString();
}
info.icon = iconPathForContent(node, KIconLoader::Small);
info.label = MimeTreeParser::Util::labelForContent(node);
bool typeBlacklisted = node->contentType()->mediaType().toLower() == "multipart";
if (!typeBlacklisted) {
typeBlacklisted = KMime::isCryptoPart(node);
}
typeBlacklisted = typeBlacklisted || node == node->topLevel();
const bool firstTextChildOfEncapsulatedMsg =
node->contentType()->mediaType().toLower() == "text" &&
node->contentType()->subType().toLower() == "plain" &&
node->parent() && node->parent()->contentType()->mediaType().toLower() == "message";
typeBlacklisted = typeBlacklisted || firstTextChildOfEncapsulatedMsg;
bool typeBlacklisted = MimeTreeParser::Util::isTypeBlacklisted(node);
info.displayInHeader = !info.label.isEmpty() && !info.icon.isEmpty() && !typeBlacklisted;
return info;
}
......@@ -40,11 +40,6 @@ namespace MessageViewer
namespace Util
{
/**
* Search mimetype from filename when mimetype is empty or application/octet-stream
**/
QMimeType MESSAGEVIEWER_EXPORT mimetype(const QString &name);
/**
* Finds the filename of an icon based on the given mimetype or filenames.
*
......@@ -61,11 +56,11 @@ QMimeType MESSAGEVIEWER_EXPORT mimetype(const QString &name);
* Example: "test.zip"
* @return the full file name of the icon file
*/
QString MESSAGEVIEWER_EXPORT fileNameForMimetype(const QString &mimeType, int iconSize,
QString MESSAGEVIEWER_EXPORT iconPathForMimetype(const QString &mimeType, int iconSize,
const QString &fallbackFileName1 = QString(),
const QString &fallbackFileName2 = QString());
QString MESSAGEVIEWER_EXPORT fileNameForContent(KMime::Content *node, int iconSize);
QString MESSAGEVIEWER_EXPORT iconPathForContent(KMime::Content *node, int iconSize);
struct AttachmentDisplayInfo {
QString label;
......
......@@ -18,9 +18,9 @@
*/
#include "mimetreemodel.h"
#include "utils/mimetype.h"
#include <MimeTreeParser/NodeHelper>
#include <MimeTreeParser/Util>
#include <KMime/Content>
#include <KMime/Message>
......@@ -92,18 +92,23 @@ public:
QIcon iconForContent(KMime::Content *content)
{
if (content->contentType(false)) {
auto iconName = MimeTreeParser::Util::iconNameForMimetype(QLatin1String(content->contentType()->mimeType()));
auto mimeType = m_mimeDb.mimeTypeForName(QString::fromLatin1(content->contentType()->mimeType()));
if (!mimeType.isValid() || mimeType.name() == QLatin1String("application/octet-stream")) {
const QString name = descriptionForContent(content);
mimeType = MessageViewer::Util::mimetype(name);
}
if (!mimeType.isValid() || mimeType.iconName().isEmpty()) {
return QIcon();
mimeType = MimeTreeParser::Util::mimetype(name);
}
if (mimeType.name().startsWith(QStringLiteral("multipart/"))) {
if (mimeType.isValid() && mimeType.name().startsWith(QStringLiteral("multipart/"))) {
return QIcon::fromTheme(QStringLiteral("folder"));
} else if (!iconName.isEmpty() && iconName != QStringLiteral("unknown")) {
return QIcon::fromTheme(iconName);
} else if (mimeType.isValid() && !mimeType.iconName().isEmpty()) {
return QIcon::fromTheme(mimeType.iconName());
}
return QIcon::fromTheme(mimeType.iconName());
return QIcon();
} else {
return QIcon();
}
......
......@@ -976,7 +976,7 @@ bool AttachmentURLHandler::handleDrag(const QUrl &url, ViewerPrivate *window) co
if (!fileName.isEmpty()) {
QFile f(fileName);
f.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther);
const QString icon = Util::fileNameForContent(node, KIconLoader::Small);
const QString icon = Util::iconPathForContent(node, KIconLoader::Small);
QDrag *drag = new QDrag(window->viewer());
QMimeData *mimeData = new QMimeData();
mimeData->setUrls(QList<QUrl>() << tUrl);
......
......@@ -333,7 +333,7 @@ void ViewerPrivate::openAttachment(KMime::Content *node, const QString &name)
}
if (!mimetype.isValid() || mimetype.name() == QLatin1String("application/octet-stream")) {
mimetype = MessageViewer::Util::mimetype(name);
mimetype = MimeTreeParser::Util::mimetype(name);
}
KService::Ptr offer =
KMimeTypeTrader::self()->preferredService(mimetype.name(), QStringLiteral("Application"));
......@@ -675,7 +675,7 @@ KService::Ptr ViewerPrivate::getServiceOffer(KMime::Content *content)
if (!mimetype.isValid() || mimetype.name() == QLatin1String("application/octet-stream")) {
/*TODO(Andris) port when on-demand loading is done && msgPart.isComplete() */
mimetype = MessageViewer::Util::mimetype(fileName);
mimetype = MimeTreeParser::Util::mimetype(fileName);
}
return KMimeTypeTrader::self()->preferredService(mimetype.name(), QStringLiteral("Application"));
}
......
......@@ -25,6 +25,7 @@ set(libmimetreeparser_main_SRCS
interfaces/htmlwriter.cpp
interfaces/messagepartrenderer.cpp
job/kleojobexecutor.cpp
utils/util.cpp
viewer/attachmentstrategy.cpp
viewer/bodypartformatter.cpp
viewer/bodypartformatterbasefactory.cpp
......@@ -41,7 +42,6 @@ set(libmimetreeparser_main_SRCS
)
set(libmimetreeparser_extra_SRCS
#for quotes
#HTML Writer
htmlwriter/filehtmlwriter.cpp
htmlwriter/queuehtmlwriter.cpp
......
/*
Copyright (c) 2016 Sandro Knauß <sknauss@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "util.h"
#include "mimetreeparser_debug.h"
#include "viewer/nodehelper.h"
#include <KMime/Content>
#include <QMimeDatabase>
#include <QString>
using namespace MimeTreeParser::Util;
bool MimeTreeParser::Util::isTypeBlacklisted(KMime::Content *node)
{
bool typeBlacklisted = node->contentType()->mediaType().toLower() == "multipart";
if (!typeBlacklisted) {
typeBlacklisted = KMime::isCryptoPart(node);
}
typeBlacklisted = typeBlacklisted || node == node->topLevel();
const bool firstTextChildOfEncapsulatedMsg =
node->contentType()->mediaType().toLower() == "text" &&
node->contentType()->subType().toLower() == "plain" &&
node->parent() && node->parent()->contentType()->mediaType().toLower() == "message";
return typeBlacklisted || firstTextChildOfEncapsulatedMsg;
}
QString MimeTreeParser::Util::labelForContent(KMime::Content *node)
{
const QString name = node->contentType()->name();
QString label = name.isEmpty() ? NodeHelper::fileName(node) : name;
if (label.isEmpty()) {
label = node->contentDescription()->asUnicodeString();
}
return label;
}
QMimeType MimeTreeParser::Util::mimetype(const QString &name)
{
QMimeDatabase db;
// consider the filename if mimetype cannot be found by content-type
auto mimeTypes = db.mimeTypesForFileName(name);
foreach (const auto &mt, mimeTypes) {
if (mt.name() != QLatin1String("application/octet-stream")) {
return mt;
}
}
// consider the attachment's contents if neither the Content-Type header
// nor the filename give us a clue
return db.mimeTypeForFile(name);
}
QString MimeTreeParser::Util::iconNameForMimetype(const QString &mimeType,
const QString &fallbackFileName1,
const QString &fallbackFileName2)
{
QString fileName;
QString tMimeType = mimeType;
// convert non-registered types to registered types
if (mimeType == QLatin1String("application/x-vnd.kolab.contact")) {
tMimeType = QStringLiteral("text/x-vcard");
} else if (mimeType == QLatin1String("application/x-vnd.kolab.event")) {
tMimeType = QStringLiteral("application/x-vnd.akonadi.calendar.event");
} else if (mimeType == QLatin1String("application/x-vnd.kolab.task")) {
tMimeType = QStringLiteral("application/x-vnd.akonadi.calendar.todo");
} else if (mimeType == QLatin1String("application/x-vnd.kolab.journal")) {
tMimeType = QStringLiteral("application/x-vnd.akonadi.calendar.journal");
} else if (mimeType == QLatin1String("application/x-vnd.kolab.note")) {
tMimeType = QStringLiteral("application/x-vnd.akonadi.note");
} else if (mimeType == QLatin1String("image/jpg")) {
tMimeType = QStringLiteral("image/jpeg");
}
QMimeDatabase mimeDb;
auto mime = mimeDb.mimeTypeForName(tMimeType);
if (mime.isValid()) {
fileName = mime.iconName();
} else {
fileName = QStringLiteral("unknown");
if (!tMimeType.isEmpty()) {
qCWarning(MIMETREEPARSER_LOG) << "unknown mimetype" << tMimeType;
}
}
//WorkAround for #199083
if (fileName == QLatin1String("text-vcard")) {
fileName = QStringLiteral("text-x-vcard");
}
if (fileName.isEmpty()) {
fileName = fallbackFileName1;
if (fileName.isEmpty()) {
fileName = fallbackFileName2;
}
if (!fileName.isEmpty()) {
fileName = mimeDb.mimeTypeForFile(QLatin1String("/tmp/") + fileName).iconName();
}
}
return fileName;
}
QString MimeTreeParser::Util::iconNameForContent(KMime::Content *node)
{
if (!node) {
return QString();
}
QByteArray mimeType = node->contentType()->mimeType();
if (mimeType.isNull() || mimeType == "application/octet-stream") {
const QString mime = mimetype(node->contentDisposition()->filename()).name();
mimeType = mime.toLatin1();
}
mimeType = mimeType.toLower();
return iconNameForMimetype(QLatin1String(mimeType), node->contentDisposition()->filename(),
node->contentType()->name());
}
\ No newline at end of file
......@@ -16,8 +16,19 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __MIMETREEPARSER_UTIL_UTIL_H__
#define __MIMETREEPARSER_UTIL_UTIL_H__
#ifndef __MIMETREEPARSER_UTILS_UTIL_H__
#define __MIMETREEPARSER_UTILS_UTIL_H__
#include "mimetreeparser_export.h"
#include <QString>
class QMimeType;
namespace KMime
{
class Content;
}
namespace MimeTreeParser
{
......@@ -40,6 +51,17 @@ enum HtmlMode {
MultipartHtml ///< A multipart/altervative message, the HTML part is currently displayed
};
bool MIMETREEPARSER_EXPORT isTypeBlacklisted(KMime::Content *node);
QString MIMETREEPARSER_EXPORT labelForContent(KMime::Content *node);
QMimeType MIMETREEPARSER_EXPORT mimetype(const QString &name);
QString MIMETREEPARSER_EXPORT iconNameForMimetype(const QString &mimeType,
const QString &fallbackFileName1 = QString(),
const QString &fallbackFileName2 = QString());
QString MIMETREEPARSER_EXPORT iconNameForContent(KMime::Content *node);
}
}
......
......@@ -34,12 +34,16 @@
#include "attachmentstrategy.h"
#include "nodehelper.h"
#include "utils/util.h"
#include <KMime/Content>
#include <QIcon>
#include <QMimeDatabase>
#include "mimetreeparser_debug.h"
namespace MimeTreeParser
{
using namespace MimeTreeParser;
static AttachmentStrategy::Display smartDisplay(KMime::Content *node)
{
......@@ -227,14 +231,10 @@ public:
return smartDisplay(node);
}
NodeHelper::AttachmentDisplayInfo info = NodeHelper::attachmentDisplayInfo(node);
if (info.displayInHeader) {
// The entire point about this attachment strategy: Hide attachments in the body that are
// already displayed in the attachment quick list
if (!Util::labelForContent(node).isEmpty() && QIcon::hasThemeIcon(Util::iconNameForContent(node)) && ! Util::isTypeBlacklisted(node)) {
return None;
} else {
return smartDisplay(node);
}
return smartDisplay(node);
}
bool requiresAttachmentListInHeader() const Q_DECL_OVERRIDE
......@@ -341,6 +341,4 @@ const AttachmentStrategy *AttachmentStrategy::headerOnly()
bool AttachmentStrategy::requiresAttachmentListInHeader() const
{
return false;
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment