File indexing completed on 2024-11-17 04:40:41

0001 /*
0002     This file is part of Akonadi Contact.
0003 
0004     SPDX-FileCopyrightText: 2009 Tobias Koenig <tokoe@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "contactgroupviewer.h"
0010 
0011 #include "job/contactgroupexpandjob.h"
0012 #include "standardcontactgroupformatter.h"
0013 #include "textbrowser_p.h"
0014 
0015 #include <Akonadi/CollectionFetchJob>
0016 #include <Akonadi/EntityDisplayAttribute>
0017 #include <Akonadi/Item>
0018 #include <Akonadi/ItemFetchScope>
0019 #include <KContacts/Addressee>
0020 #include <KContacts/ContactGroup>
0021 
0022 #include <KLocalizedString>
0023 
0024 #include <QIcon>
0025 #include <QVBoxLayout>
0026 
0027 using namespace Akonadi;
0028 using namespace Akonadi;
0029 
0030 class Akonadi::ContactGroupViewerPrivate
0031 {
0032 public:
0033     explicit ContactGroupViewerPrivate(ContactGroupViewer *parent)
0034         : mParent(parent)
0035     {
0036         mBrowser = new Akonadi::TextBrowser;
0037 
0038         static QPixmap groupPixmap = QIcon::fromTheme(QStringLiteral("x-mail-distribution-list")).pixmap(QSize(100, 100));
0039         mBrowser->document()->addResource(QTextDocument::ImageResource, QUrl(QStringLiteral("group_photo")), groupPixmap);
0040 
0041         mStandardContactGroupFormatter = new StandardContactGroupFormatter;
0042         mContactGroupFormatter = mStandardContactGroupFormatter;
0043     }
0044 
0045     ~ContactGroupViewerPrivate()
0046     {
0047         delete mStandardContactGroupFormatter;
0048     }
0049 
0050     void updateView()
0051     {
0052         mParent->setWindowTitle(i18nc("@title:window", "Contact Group %1", mCurrentGroupName));
0053 
0054         KContacts::ContactGroup group;
0055         group.setName(mCurrentGroupName);
0056         for (const KContacts::Addressee &contact : std::as_const(mCurrentContacts)) {
0057             group.append(KContacts::ContactGroup::Data(contact.realName(), contact.preferredEmail()));
0058         }
0059 
0060         mContactGroupFormatter->setContactGroup(group);
0061 
0062         QList<QVariantMap> additionalFields;
0063 
0064         if (!mCurrentAddressBookName.isEmpty()) {
0065             QVariantMap addressBookName;
0066             addressBookName.insert(QStringLiteral("title"), i18n("Address Book"));
0067             addressBookName.insert(QStringLiteral("value"), mCurrentAddressBookName);
0068 
0069             additionalFields << addressBookName;
0070         }
0071 
0072         mContactGroupFormatter->setAdditionalFields(additionalFields);
0073 
0074         mBrowser->setHtml(mContactGroupFormatter->toHtml());
0075     }
0076 
0077     void _k_expandResult(KJob *job)
0078     {
0079         mExpandJob = nullptr;
0080 
0081         if (!job->error()) {
0082             auto expandJob = qobject_cast<ContactGroupExpandJob *>(job);
0083             mCurrentContacts = expandJob->contacts();
0084         }
0085 
0086         // stop any running fetch job
0087         if (mParentCollectionFetchJob) {
0088             mParent->disconnect(mCollectionFetchJobConnection);
0089             delete mParentCollectionFetchJob;
0090             mParentCollectionFetchJob = nullptr;
0091         }
0092 
0093         mParentCollectionFetchJob = new CollectionFetchJob(mCurrentItem.parentCollection(), CollectionFetchJob::Base, mParent);
0094         mCollectionFetchJobConnection = mParent->connect(mParentCollectionFetchJob, &CollectionFetchJob::result, mParent, [this](KJob *job) {
0095             slotParentCollectionFetched(job);
0096         });
0097     }
0098 
0099     void slotParentCollectionFetched(KJob *job)
0100     {
0101         mParentCollectionFetchJob = nullptr;
0102         mCurrentAddressBookName.clear();
0103 
0104         if (!job->error()) {
0105             auto fetchJob = qobject_cast<CollectionFetchJob *>(job);
0106             if (!fetchJob->collections().isEmpty()) {
0107                 const Collection collection = fetchJob->collections().at(0);
0108                 mCurrentAddressBookName = collection.displayName();
0109             }
0110         }
0111 
0112         updateView();
0113     }
0114 
0115     QMetaObject::Connection mCollectionFetchJobConnection;
0116     QMetaObject::Connection mJobConnection;
0117     ContactGroupViewer *const mParent;
0118     Akonadi::TextBrowser *mBrowser = nullptr;
0119     QString mCurrentGroupName;
0120     KContacts::Addressee::List mCurrentContacts;
0121     QString mCurrentAddressBookName;
0122     Item mCurrentItem;
0123     ContactGroupExpandJob *mExpandJob = nullptr;
0124     CollectionFetchJob *mParentCollectionFetchJob = nullptr;
0125     AbstractContactGroupFormatter *mStandardContactGroupFormatter = nullptr;
0126     AbstractContactGroupFormatter *mContactGroupFormatter = nullptr;
0127 };
0128 
0129 ContactGroupViewer::ContactGroupViewer(QWidget *parent)
0130     : QWidget(parent)
0131     , d(new ContactGroupViewerPrivate(this))
0132 {
0133     auto layout = new QVBoxLayout(this);
0134     layout->setContentsMargins({});
0135 
0136     connect(d->mBrowser, &Akonadi::TextBrowser::anchorClicked, this, &ContactGroupViewer::urlClicked);
0137 
0138     layout->addWidget(d->mBrowser);
0139 
0140     // always fetch full payload for contact groups
0141     fetchScope().fetchFullPayload();
0142     fetchScope().setAncestorRetrieval(ItemFetchScope::Parent);
0143 }
0144 
0145 ContactGroupViewer::~ContactGroupViewer() = default;
0146 
0147 Akonadi::Item ContactGroupViewer::contactGroup() const
0148 {
0149     return ItemMonitor::item();
0150 }
0151 
0152 void ContactGroupViewer::setContactGroup(const Akonadi::Item &group)
0153 {
0154     ItemMonitor::setItem(group);
0155 }
0156 
0157 void ContactGroupViewer::setContactGroupFormatter(AbstractContactGroupFormatter *formatter)
0158 {
0159     if (formatter == nullptr) {
0160         d->mContactGroupFormatter = d->mStandardContactGroupFormatter;
0161     } else {
0162         d->mContactGroupFormatter = formatter;
0163     }
0164 }
0165 
0166 void ContactGroupViewer::updateView()
0167 {
0168     itemChanged(d->mCurrentItem);
0169 }
0170 
0171 void ContactGroupViewer::itemChanged(const Item &item)
0172 {
0173     if (!item.hasPayload<KContacts::ContactGroup>()) {
0174         return;
0175     }
0176 
0177     const auto group = item.payload<KContacts::ContactGroup>();
0178     d->mCurrentGroupName = group.name();
0179     d->mCurrentItem = item;
0180 
0181     if (d->mExpandJob) {
0182         disconnect(d->mJobConnection);
0183         d->mExpandJob->kill();
0184     }
0185 
0186     d->mExpandJob = new ContactGroupExpandJob(group);
0187     d->mJobConnection = connect(d->mExpandJob, &ContactGroupExpandJob::result, this, [this](KJob *job) {
0188         d->_k_expandResult(job);
0189     });
0190     d->mExpandJob->start();
0191 }
0192 
0193 void ContactGroupViewer::itemRemoved()
0194 {
0195     d->mBrowser->clear();
0196 }
0197 
0198 #include "moc_contactgroupviewer.cpp"