[SMS App] Add thumbnail preview to ConversationList

This commit is contained in:
Simon Redman 2020-09-27 03:51:17 +00:00
parent cb51cb4adf
commit 8dd0111d99
5 changed files with 68 additions and 5 deletions

View file

@ -32,6 +32,7 @@ ConversationListModel::ConversationListModel(QObject* parent)
roles.insert(AddressesRole, "addresses");
roles.insert(ConversationIdRole, "conversationId");
roles.insert(MultitargetRole, "isMultitarget");
roles.insert(AttachmentPreview, "attachmentPreview");
setItemRoleNames(roles);
ConversationMessage::registerDbusType();
@ -190,19 +191,23 @@ void ConversationListModel::createRowFromMessage(const ConversationMessage& mess
displayBody = message.body();
} else if (message.containsAttachment()) {
const QString mimeType = message.attachments().last().mimeType();
QString type;
if (mimeType.startsWith(QStringLiteral("image"))) {
type = i18nc("Used as a text placeholder when the most-recent message is an image", "Picture");
displayBody = i18nc("Used as a text placeholder when the most-recent message is an image", "Picture");
}
else if (mimeType.startsWith(QStringLiteral("video"))) {
type = i18nc("Used as a text placeholder when the most-recent message is a video", "Video");
displayBody = i18nc("Used as a text placeholder when the most-recent message is a video", "Video");
} else {
// Craft a somewhat-descriptive string, like "pdf file"
type = i18nc("Used as a text placeholder when the most-recent message is an arbitrary attachment, resulting in something like \"pdf file\"",
displayBody = i18nc("Used as a text placeholder when the most-recent message is an arbitrary attachment, resulting in something like \"pdf file\"",
"%1 file",
mimeType.right(mimeType.indexOf(QStringLiteral("/"))));
}
displayBody = type;
}
// Get the preview from the attachment, if it exists
QIcon attachmentPreview;
if (message.containsAttachment()) {
attachmentPreview = SmsHelper::getThumbnailForAttachment(message.attachments().last());
}
// For displaying single line subtitle out of the multiline messages to keep the ListItems consistent
@ -231,6 +236,9 @@ void ConversationListModel::createRowFromMessage(const ConversationMessage& mess
item->setData(displayBody, Qt::ToolTipRole);
item->setData(message.date(), DateRole);
item->setData(message.isMultitarget(), MultitargetRole);
if (!attachmentPreview.isNull()) {
item->setData(attachmentPreview, AttachmentPreview);
}
}
if (toadd)

View file

@ -32,6 +32,7 @@ public:
AddressesRole, // The Addresses involved in the conversation
ConversationIdRole, // The ThreadID of the conversation
MultitargetRole, // Indicate that this conversation is multitarget
AttachmentPreview, // A thumbnail of the attachment of the message, if any
};
Q_ENUM(Roles)

View file

@ -221,6 +221,7 @@ Kirigami.ScrollablePage
label: display
subtitle: toolTip
property var thumbnail: attachmentPreview
function startChat() {
applicationWindow().pageStack.push(chatView, {
@ -236,6 +237,30 @@ Kirigami.ScrollablePage
startChat();
view.currentIndex = index
}
Kirigami.Icon {
id: thumbnailItem
source: {
if (!listItem.thumbnail) {
return undefined
}
if (listItem.thumbnail.hasOwnProperty) {
if (listItem.thumbnail.hasOwnProperty("name") && listItem.thumbnail.name !== "")
return listItem.thumbnail.name;
if (listItem.thumbnail.hasOwnProperty("source"))
return listItem.thumbnail.source;
}
return listItem.thumbnail;
}
property int size: Kirigami.Units.iconSizes.huge
Layout.minimumHeight: size
Layout.maximumHeight: size
Layout.minimumWidth: size
selected: (listItem.highlighted || listItem.checked || (listItem.pressed && listItem.supportsMouseEvents))
opacity: 1
visible: source != undefined
}
// Keep the currently-open chat highlighted even if this element is not focused
highlighted: view.currentIndex == index
}

View file

@ -9,6 +9,8 @@
#include <QClipboard>
#include <QGuiApplication>
#include <QIcon>
#include <QMimeDatabase>
#include <QMimeType>
#include <QPainter>
#include <QRegularExpression>
#include <QString>
@ -453,3 +455,25 @@ quint64 SmsHelper::totalMessageSize(const QList<QUrl>& urls, const QString& text
return totalSize;
}
QIcon SmsHelper::getThumbnailForAttachment(const Attachment& attachment) {
static const QMimeDatabase mimeDatabase;
const QByteArray rawData = QByteArray::fromBase64(attachment.base64EncodedFile().toUtf8());
if (attachment.mimeType().startsWith(QStringLiteral("image"))
|| attachment.mimeType().startsWith(QStringLiteral("video"))) {
QPixmap preview;
preview.loadFromData(rawData);
return QIcon(preview);
} else {
const QMimeType mimeType = mimeDatabase.mimeTypeForData(rawData);
const QIcon mimeIcon = QIcon::fromTheme(mimeType.iconName());
if (mimeIcon.isNull()) {
// I am not sure if QIcon::isNull will actually tell us what we care about but I don't
// know how to trigger the case where we need to use genericIconName instead of iconName
return QIcon::fromTheme(mimeType.genericIconName());
} else {
return mimeIcon;
}
}
}

View file

@ -120,6 +120,11 @@ public:
*/
Q_INVOKABLE static quint64 totalMessageSize(const QList<QUrl>& urls, const QString& text);
/**
* Gets a thumbnail for the given attachment
*/
Q_INVOKABLE static QIcon getThumbnailForAttachment(const Attachment& attachment);
private:
static bool isInGsmAlphabet(const QChar& ch);
static bool isInGsmAlphabetExtension(const QChar& ch);