Commit 321ae468 authored by Carl Schwan's avatar Carl Schwan 🚴 Committed by Claudio Cambra
Browse files

Show unread mail



Signed-off-by: Carl Schwan's avatarCarl Schwan <carl@carlschwan.eu>
parent f295a3df
......@@ -11,6 +11,9 @@ target_sources(kalendar_mail_plugin PRIVATE
mailmodel.cpp
mailmodel.h
messagestatus.h
messagestatus.cpp
crypto.cpp
mimetreeparser/messagepart.cpp
mimetreeparser/bodypartformatter.cpp
......
......@@ -4,20 +4,17 @@
#include "mailmodel.h"
//#include "messagewrapper.h"
//#include "messageviewer/viewer.h"
#include "messagestatus.h"
#include <Akonadi/EntityTreeModel>
#include <Akonadi/ItemModifyJob>
#include <Akonadi/MessageStatus>
#include <KFormat>
#include <KLocalizedString>
#include <KMime/Message>
#include <QQmlEngine>
#include <kformat.h>
#include <qvariant.h>
MailModel::MailModel(QObject *parent)
: QIdentityProxyModel(parent)
// , m_viewerHelper(new ViewerHelper(this))
{
}
......@@ -30,7 +27,7 @@ QHash<int, QByteArray> MailModel::roleNames() const
{SenderRole, QByteArrayLiteral("sender")},
{FromRole, QByteArrayLiteral("from")},
{ToRole, QByteArrayLiteral("to")},
{UnreadRole, QByteArrayLiteral("unread")},
{StatusRole, QByteArrayLiteral("status")},
{FavoriteRole, QByteArrayLiteral("favorite")},
{TextColorRole, QByteArrayLiteral("textColor")},
{BackgroundColorRole, QByteArrayLiteral("backgroudColor")},
......@@ -49,51 +46,17 @@ QVariant MailModel::data(const QModelIndex &index, int role) const
}
const KMime::Message::Ptr mail = item.payload<KMime::Message::Ptr>();
//const Collection parentCol = parentCollectionForRow(row);
QString sender;
if (mail->from()) {
sender = mail->from()->asUnicodeString();
}
QString receiver;
if (mail->to()) {
receiver = mail->to()->asUnicodeString();
}
// Static for speed reasons
static const QString noSubject = i18nc("displayed as subject when the subject of a mail is empty", "No Subject");
static const QString unknown(i18nc("displayed when a mail has unknown sender, receiver or date", "Unknown"));
if (sender.isEmpty()) {
sender = unknown;
}
if (receiver.isEmpty()) {
receiver = unknown;
}
//mi->initialSetup(mail->date()->dateTime().toSecsSinceEpoch(), item.size(), sender, receiver, bUseReceiver);
//mi->setItemId(item.id());
//mi->setParentCollectionId(parentCol.id());
QString subject = mail->subject()->asUnicodeString();
if (subject.isEmpty()) {
subject = QLatin1Char('(') + noSubject + QLatin1Char(')');
}
//mi->setSubject(subject);
//auto it = d->mFolderHash.find(item.storageCollectionId());
//if (it == d->mFolderHash.end()) {
// QString folder;
// Collection collection = collectionForId(item.storageCollectionId());
// while (collection.parentCollection().isValid()) {
// folder = collection.displayName() + QLatin1Char('/') + folder;
// collection = collection.parentCollection();
// }
// folder.chop(1);
// it = d->mFolderHash.insert(item.storageCollectionId(), folder);
//}
//mi->setFolder(it.value());
MessageStatus stat;
stat.setStatusFromFlags(item.flags());
// NOTE: remember to update AkonadiBrowserSortModel::lessThan if you insert/move columns
switch (role) {
......@@ -101,7 +64,7 @@ QVariant MailModel::data(const QModelIndex &index, int role) const
if (mail->subject()) {
return mail->subject()->asUnicodeString();
} else {
return QStringLiteral("(No subject)");
return noSubject;
}
case FromRole:
if (mail->from()) {
......@@ -117,9 +80,9 @@ QVariant MailModel::data(const QModelIndex &index, int role) const
}
case ToRole:
if (mail->to()) {
return mail->sender()->asUnicodeString();
return mail->to()->asUnicodeString();
} else {
return QString();
return unknown;
}
case DateRole:
if (mail->date()) {
......@@ -134,6 +97,8 @@ QVariant MailModel::data(const QModelIndex &index, int role) const
} else {
return QString();
}
case StatusRole:
return QVariant::fromValue(stat);
case ItemRole:
return QVariant::fromValue(item);
}
......@@ -141,28 +106,25 @@ QVariant MailModel::data(const QModelIndex &index, int role) const
return {};
}
void MailModel::loadItem(int row)
Akonadi::Item MailModel::itemForRow(int row) const
{
//if (!m_viewerHelper) {
// return;
//}
QVariant itemVariant = sourceModel()->data(mapToSource(index(row, 0)), Akonadi::EntityTreeModel::ItemRole);
return data(index(row, 0), ItemRole).value<Akonadi::Item>();
}
Akonadi::Item item = itemVariant.value<Akonadi::Item>();
void MailModel::updateMessageStatus(int row, MessageStatus messageStatus)
{
Akonadi::Item item = itemForRow(row);
item.setFlags(messageStatus.statusFlags());
auto job = new Akonadi::ItemModifyJob(item, this);
job->disableRevisionCheck();
job->setIgnorePayload(true);
//m_viewerHelper->setMessageItem(item);
Q_EMIT dataChanged(index(row, 0), index(row, 0), {StatusRole});
}
//void MailModel::setViewerHelper(ViewerHelper *viewerHelper)
//{
// if (m_viewerHelper == viewerHelper) {
// return;
// }
// m_viewerHelper = viewerHelper;
// Q_EMIT viewerHelperChanged();
//}
//
//ViewerHelper *MailModel::viewerHelper() const
//{
// return m_viewerHelper;
//}
MessageStatus MailModel::copyMessageStatus(MessageStatus messageStatus)
{
MessageStatus newStatus;
newStatus.set(messageStatus);
return messageStatus;
}
......@@ -4,18 +4,19 @@
#pragma once
#include <QObject>
#include <Akonadi/Item>
#include <QIdentityProxyModel>
#include <QItemSelectionModel>
#include <QObject>
//class ViewerHelper;
#include "messagestatus.h"
class MailModel : public QIdentityProxyModel
{
Q_OBJECT
public:
enum AnimalRoles {
enum ExtraRole {
TitleRole = Qt::UserRole + 1,
SenderRole,
FromRole,
......@@ -24,7 +25,7 @@ public:
DateRole,
DateTimeRole,
BackgroundColorRole,
UnreadRole,
StatusRole,
FavoriteRole,
ItemRole,
};
......@@ -33,5 +34,9 @@ public:
QHash<int, QByteArray> roleNames() const override;
virtual QVariant data(const QModelIndex &index, int role) const override;
Q_INVOKABLE void loadItem(int row);
Q_INVOKABLE void updateMessageStatus(int row, MessageStatus messageStatus);
Q_INVOKABLE MessageStatus copyMessageStatus(MessageStatus messageStatus);
private:
Akonadi::Item itemForRow(int row) const;
};
/*
This file is part of Akonadi.
SPDX-FileCopyrightText: 2003 Andreas Gungl <a.gungl@gmx.de>
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
SPDX-FileCopyrightText: 2010 Leo Franchi <lfranchi@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "messagestatus.h"
#include <Akonadi/MessageFlags>
#include <QString>
using namespace Akonadi;
/** The message status format. These can be or'd together.
Note, that the StatusIgnored implies the
status to be Read.
This is done in isRead() and related getters.
So we can preserve the state when switching a
thread to Ignored and back. */
enum Status {
StatusUnknown = 0x00000000,
StatusUnread = 0x00000002, // deprecated
StatusRead = 0x00000004,
StatusDeleted = 0x00000010,
StatusReplied = 0x00000020,
StatusForwarded = 0x00000040,
StatusQueued = 0x00000080,
StatusSent = 0x00000100,
StatusFlag = 0x00000200, // flag means important
StatusWatched = 0x00000400,
StatusIgnored = 0x00000800, // forces isRead()
StatusToAct = 0x00001000,
StatusSpam = 0x00002000,
StatusHam = 0x00004000,
StatusHasAttachment = 0x00008000,
StatusHasInvitation = 0x00010000,
StatusSigned = 0x00020000,
StatusEncrypted = 0x00040000,
StatusHasError = 0x00080000
};
MessageStatus::MessageStatus()
{
mStatus = StatusUnknown;
}
bool MessageStatus::operator==(MessageStatus other) const
{
return mStatus == other.mStatus;
}
bool MessageStatus::operator!=(MessageStatus other) const
{
return mStatus != other.mStatus;
}
bool MessageStatus::operator&(MessageStatus other) const
{
if (mStatus == StatusUnread) {
return !(other.mStatus & StatusRead);
}
if (other.mStatus == StatusUnread) {
return !(mStatus & StatusRead);
}
return mStatus & other.mStatus;
}
void MessageStatus::clear()
{
mStatus = StatusUnknown;
}
void MessageStatus::set(MessageStatus other)
{
Q_ASSERT(!(other.mStatus & StatusUnread));
// Those static are exclusive, but we have to lock at the
// internal representation because Ignored can manipulate
// the result of the getter methods.
if (other.mStatus & StatusRead) {
setRead();
}
if (other.isDeleted()) {
setDeleted();
}
if (other.isReplied()) {
setReplied();
}
if (other.isForwarded()) {
setForwarded();
}
if (other.isQueued()) {
setQueued();
}
if (other.isSent()) {
setSent();
}
if (other.isImportant()) {
setImportant();
}
if (other.isWatched()) {
setWatched();
}
if (other.isIgnored()) {
setIgnored();
}
if (other.isToAct()) {
setToAct();
}
if (other.isSpam()) {
setSpam();
}
if (other.isHam()) {
setHam();
}
if (other.hasAttachment()) {
setHasAttachment();
}
if (other.hasInvitation()) {
setHasInvitation();
}
if (other.isSigned()) {
setSigned();
}
if (other.isEncrypted()) {
setEncrypted();
}
if (other.hasError()) {
setHasError();
}
}
void MessageStatus::toggle(MessageStatus other)
{
Q_ASSERT(!(other.mStatus & StatusUnread));
if (other.isDeleted()) {
setDeleted(!(mStatus & StatusDeleted));
}
if (other.isReplied()) {
setReplied(!(mStatus & StatusReplied));
}
if (other.isForwarded()) {
setForwarded(!(mStatus & StatusForwarded));
}
if (other.isQueued()) {
setQueued(!(mStatus & StatusQueued));
}
if (other.isSent()) {
setSent(!(mStatus & StatusSent));
}
if (other.isImportant()) {
setImportant(!(mStatus & StatusFlag));
}
if (other.isWatched()) {
setWatched(!(mStatus & StatusWatched));
}
if (other.isIgnored()) {
setIgnored(!(mStatus & StatusIgnored));
}
if (other.isToAct()) {
setToAct(!(mStatus & StatusToAct));
}
if (other.isSpam()) {
setSpam(!(mStatus & StatusSpam));
}
if (other.isHam()) {
setHam(!(mStatus & StatusHam));
}
if (other.hasAttachment()) {
setHasAttachment(!(mStatus & StatusHasAttachment));
}
if (other.hasInvitation()) {
setHasInvitation(!(mStatus & StatusHasInvitation));
}
if (other.isSigned()) {
setSigned(!(mStatus & StatusSigned));
}
if (other.isEncrypted()) {
setEncrypted(!(mStatus & StatusEncrypted));
}
if (other.hasError()) {
setHasError(!(mStatus & StatusHasError));
}
}
bool MessageStatus::isOfUnknownStatus() const
{
return mStatus == StatusUnknown;
}
bool MessageStatus::isRead() const
{
return (mStatus & StatusRead) || (mStatus & StatusIgnored);
}
bool MessageStatus::isDeleted() const
{
return mStatus & StatusDeleted;
}
bool MessageStatus::isReplied() const
{
return mStatus & StatusReplied;
}
bool MessageStatus::isForwarded() const
{
return mStatus & StatusForwarded;
}
bool MessageStatus::isQueued() const
{
return mStatus & StatusQueued;
}
bool MessageStatus::isSent() const
{
return mStatus & StatusSent;
}
bool MessageStatus::isImportant() const
{
return mStatus & StatusFlag;
}
bool MessageStatus::isWatched() const
{
return mStatus & StatusWatched;
}
bool MessageStatus::isIgnored() const
{
return mStatus & StatusIgnored;
}
bool MessageStatus::isToAct() const
{
return mStatus & StatusToAct;
}
bool MessageStatus::isSpam() const
{
return mStatus & StatusSpam;
}
bool MessageStatus::isHam() const
{
return mStatus & StatusHam;
}
bool MessageStatus::hasAttachment() const
{
return mStatus & StatusHasAttachment;
}
bool MessageStatus::hasInvitation() const
{
return mStatus & StatusHasInvitation;
}
bool MessageStatus::isSigned() const
{
return mStatus & StatusSigned;
}
bool MessageStatus::isEncrypted() const
{
return mStatus & StatusEncrypted;
}
bool MessageStatus::hasError() const
{
return mStatus & StatusHasError;
}
void MessageStatus::setRead(bool read)
{
if (read) {
mStatus |= StatusRead;
} else {
mStatus &= ~StatusRead;
}
}
void MessageStatus::setDeleted(bool deleted)
{
if (deleted) {
mStatus |= StatusDeleted;
} else {
mStatus &= ~StatusDeleted;
}
}
void MessageStatus::setReplied(bool replied)
{
if (replied) {
mStatus |= StatusReplied;
} else {
mStatus &= ~StatusReplied;
}
}
void MessageStatus::setForwarded(bool forwarded)
{
if (forwarded) {
mStatus |= StatusForwarded;
} else {
mStatus &= ~StatusForwarded;
}
}
void MessageStatus::setQueued(bool queued)
{
if (queued) {
mStatus |= StatusQueued;
} else {
mStatus &= ~StatusQueued;
}
}
void MessageStatus::setSent(bool sent)
{
if (sent) {
mStatus &= ~StatusQueued;
mStatus |= StatusSent;
} else {
mStatus &= ~StatusSent;
}
}
void MessageStatus::setImportant(bool important)
{
if (important) {
mStatus |= StatusFlag;
} else {
mStatus &= ~StatusFlag;
}
}
// Watched and ignored are mutually exclusive
void MessageStatus::setWatched(bool watched)
{
if (watched) {
mStatus &= ~StatusIgnored;
mStatus |= StatusWatched;
} else {
mStatus &= ~StatusWatched;
}
}
void MessageStatus::setIgnored(bool ignored)
{
if (ignored) {
mStatus &= ~StatusWatched;
mStatus |= StatusIgnored;
} else {
mStatus &= ~StatusIgnored;
}
}
void MessageStatus::setToAct(bool toAct)
{
if (toAct) {
mStatus |= StatusToAct;
} else {
mStatus &= ~StatusToAct;
}
}
// Ham and Spam are mutually exclusive
void MessageStatus::setSpam(bool spam)
{
if (spam) {
mStatus &= ~StatusHam;
mStatus |= StatusSpam;
} else {
mStatus &= ~StatusSpam;
}
}
void MessageStatus::setHam(bool ham)
{
if (ham) {
mStatus &= ~StatusSpam;
mStatus |= StatusHam;
} else {
mStatus &= ~StatusHam;
}
}
void MessageStatus::setHasAttachment(bool withAttachment)
{
if (withAttachment) {
mStatus |= StatusHasAttachment;
} else {
mStatus &= ~StatusHasAttachment;
}
}
void MessageStatus::setHasInvitation(bool withInvitation)
{
if (withInvitation) {
mStatus |= StatusHasInvitation;
} else {
mStatus &= ~StatusHasInvitation;
}
}