Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
PIM
Kalendar
Commits
321ae468
Commit
321ae468
authored
Jun 12, 2022
by
Carl Schwan
🚴
Committed by
Claudio Cambra
Aug 04, 2022
Browse files
Show unread mail
Signed-off-by:
Carl Schwan
<
carl@carlschwan.eu
>
parent
f295a3df
Changes
6
Hide whitespace changes
Inline
Side-by-side
src/mail/CMakeLists.txt
View file @
321ae468
...
...
@@ -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
...
...
src/mail/mailmodel.cpp
View file @
321ae468
...
...
@@ -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"
)},
{
Unread
Role
,
QByteArrayLiteral
(
"
unread
"
)},
{
Status
Role
,
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 s
ubject
)"
)
;
return
noS
ubject
;
}
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
;
}
src/mail/mailmodel.h
View file @
321ae468
...
...
@@ -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
Animal
Role
s
{
enum
Extra
Role
{
TitleRole
=
Qt
::
UserRole
+
1
,
SenderRole
,
FromRole
,
...
...
@@ -24,7 +25,7 @@ public:
DateRole
,
DateTimeRole
,
BackgroundColorRole
,
Unread
Role
,
Status
Role
,
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
;
};
src/mail/messagestatus.cpp
0 → 100644
View file @
321ae468
/*
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
;
}
}