1 /*
2   This file is part of KAddressBook.
3 
4   SPDX-FileCopyrightText: 2020 Konrad Czapla <kondzio89dev@gmail.com>
5 
6   SPDX-License-Identifier: GPL-2.0-or-later
7 */
8 
9 #pragma once
10 
11 #include <Akonadi/EntityTreeModel>
12 #include <KContacts/ContactGroup>
13 #include <QIdentityProxyModel>
14 #include <QObject>
15 
16 namespace Akonadi
17 {
18 class Item;
19 class Monitor;
20 }
21 
22 namespace KContacts
23 {
24 class Addressee;
25 class ContactGroup;
26 }
27 class ContactInfoProxyModel : public QIdentityProxyModel
28 {
29     Q_OBJECT
30 public:
31     enum Roles {
32         PictureRole = Akonadi::EntityTreeModel::UserRole,
33         InitialsRole,
34         DescriptionRole,
35     };
36 
37     explicit ContactInfoProxyModel(QObject *parent = nullptr);
38     QVariant data(const QModelIndex &index, int role) const override;
39 
40 private:
41     class ContactCacheData
42     {
43     public:
44         using List = QVector<ContactCacheData>;
45         using ListIterator = ContactCacheData::List::iterator;
46         using ConstListIterator = ContactCacheData::List::ConstIterator;
47 
48         ContactCacheData() = default;
49         ~ContactCacheData() = default;
50         ContactCacheData(const ContactCacheData &) = default;
51 
ContactCacheData(const KContacts::ContactGroup::ContactReference & other)52         ContactCacheData(const KContacts::ContactGroup::ContactReference &other)
53             : mUid(other.uid())
54             , mGid(other.gid())
55         {
56         }
57 
ContactCacheData(const Akonadi::Item & other)58         ContactCacheData(const Akonadi::Item &other)
59             : mUid(QString::number(other.id()))
60             , mGid(other.gid())
61         {
62         }
63 
64         Q_REQUIRED_RESULT bool setData(const Akonadi::Item &item);
65 
66         friend bool operator==(const ContactCacheData &lhs, const ContactCacheData &rhs);
67 
uid()68         Q_REQUIRED_RESULT QString uid() const
69         {
70             return mUid;
71         }
gid()72         Q_REQUIRED_RESULT QString gid() const
73         {
74             return mGid;
75         }
name()76         Q_REQUIRED_RESULT QString name() const
77         {
78             return mName;
79         }
email()80         Q_REQUIRED_RESULT QString email() const
81         {
82             return mEmail;
83         }
84 
85     private:
86         Q_REQUIRED_RESULT bool validateItem(const Akonadi::Item &item) const;
87         QString mUid;
88         QString mGid;
89         QString mName;
90         QString mEmail;
91     };
92 
93     Q_REQUIRED_RESULT QString getInitials(const KContacts::Addressee &contact) const;
94     Q_REQUIRED_RESULT QString getInitials(const Akonadi::Item::Id groupItemId, const KContacts::ContactGroup &groupContacts) const;
95     Q_REQUIRED_RESULT QString getDescription(const KContacts::Addressee &contact) const;
96     Q_REQUIRED_RESULT QString getDescription(const Akonadi::Item::Id groupItemId, const KContacts::ContactGroup &groupContacts) const;
97     Q_REQUIRED_RESULT QStringList getIdsContactGroup(const KContacts::ContactGroup &group) const;
98     Q_REQUIRED_RESULT QStringList getIdsCacheContactGroup(const Akonadi::Item::Id groupItemId) const;
99     Q_REQUIRED_RESULT bool isCacheItemToFetch(const Akonadi::Item::Id groupItemId, const KContacts::ContactGroup &group) const;
100     Q_REQUIRED_RESULT ContactCacheData::ListIterator findCacheItem(const Akonadi::Item::Id groupItemId, const ContactCacheData &cacheContact);
101     Q_REQUIRED_RESULT ContactCacheData::ConstListIterator findCacheItem(const Akonadi::Item::Id groupItemId, const ContactCacheData &cacheContact) const;
102     Q_REQUIRED_RESULT QMap<const char *, QVariant> buildFetchProperties(const Akonadi::Item::Id groupItemId) const;
103 
104     void resolveGroup(const Akonadi::Item::Id groupItemId, const KContacts::ContactGroup &groupContacts) const;
105     void fetchItems(const Akonadi::Item::List &items, const QMap<const char *, QVariant> &properties) const;
106 
107     void slotFetchJobFinished(KJob *job);
108     void slotItemChanged(const Akonadi::Item &item, const QSet<QByteArray> &partIdentifiers);
109     void slotRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
110 
111     friend bool operator==(const ContactCacheData &lhs, const ContactCacheData &rhs);
112     using Cache = QMap<Akonadi::Item::Id, ContactCacheData::List>;
113     mutable Cache mGroupsCache;
114     mutable QList<Akonadi::Item::Id> mPendingGroupItems;
115     const QVector<int> mKrole{PictureRole, InitialsRole, DescriptionRole};
116     Akonadi::Monitor *const mMonitor;
117 };
118 
119