File indexing completed on 2024-11-24 04:50:41

0001 // This file is part of Akonadi Contact.
0002 // SPDX-FileCopyrightText: 2009 Tobias Koenig <tokoe@kde.org>
0003 // SPDX-License-Identifier: LGPL-2.0-or-later
0004 
0005 #pragma once
0006 
0007 #include "contactmetadata.h"
0008 #include <Akonadi/Collection>
0009 #include <Akonadi/Item>
0010 #include <QObject>
0011 
0012 namespace KContacts
0013 {
0014 class Addressee;
0015 }
0016 
0017 namespace Akonadi
0018 {
0019 class Monitor;
0020 }
0021 
0022 class AddresseeWrapper;
0023 
0024 /**
0025  * @short An object to edit contacts in Akonadi.
0026  *
0027  * This object provides a way to create a new contact or edit
0028  * an existing contact in Akonadi from QML.
0029  *
0030  * Example for creating a new contact:
0031  *
0032  * @code{.qml}
0033  * ContactEditor {
0034  *     id: contactEditor
0035  *     mode: ContactEditor.CreateMode
0036  * }
0037  *
0038  * TextField {
0039  *     id: nameField
0040  *     onTextChanged. contactEditor.addressee.name = text
0041  * }
0042  *
0043  * Button {
0044  *     onClicked: contactEditor.saveContactInAddressBook()
0045  * }
0046  * @endcode
0047  *
0048  * Example for editing an existing contact:
0049  *
0050  * @code
0051  *
0052  * ContactEditor {
0053  *     id: contactEditor
0054  *     mode: ContactEditor.EditMode
0055  *     item: myExistingItem
0056  * }
0057  *
0058  * TextField {
0059  *     id: nameField
0060  *     onTextChanged. contactEditor.addressee.name = text
0061  * }
0062  *
0063  * Button {
0064  *     onClicked: contactEditor.saveContactInAddressBook()
0065  * }
0066  *
0067  * @endcode
0068  *
0069  * @author Tobias Koenig <tokoe@kde.org>
0070  * @author Carl Schwan <carl@carlschwan.eu>
0071  */
0072 class ContactEditorBackend : public QObject
0073 {
0074     Q_OBJECT
0075     Q_PROPERTY(Mode mode READ mode WRITE setMode NOTIFY modeChanged)
0076     Q_PROPERTY(AddresseeWrapper *contact READ contact NOTIFY contactChanged NOTIFY modeChanged)
0077     Q_PROPERTY(Akonadi::Item item READ item WRITE setItem NOTIFY itemChanged)
0078     Q_PROPERTY(qint64 collectionId READ collectionId WRITE setCollectionId NOTIFY collectionChanged)
0079     Q_PROPERTY(bool isReadOnly READ isReadOnly NOTIFY addresseeChanged NOTIFY modeChanged)
0080 
0081 public:
0082     /**
0083      * Describes the mode of the editor.
0084      */
0085     enum Mode {
0086         CreateMode, ///< Creates a new contact
0087         EditMode ///< Edits an existing contact
0088     };
0089     Q_ENUM(Mode)
0090 
0091     /**
0092      * Creates a new contact editor backend.
0093      *
0094      * @param parent The parent object of the editor.
0095      */
0096     explicit ContactEditorBackend(QObject *parent = nullptr);
0097 
0098     /**
0099      * Destroys the contact editor.
0100      */
0101     ~ContactEditorBackend() override;
0102 
0103     /**
0104      * Sets the @p addressbook which shall be used to store new
0105      * contacts.
0106      */
0107     Q_INVOKABLE void setDefaultAddressBook(const Akonadi::Collection &addressbook);
0108 
0109     [[nodiscard]] bool hasNoSavedData() const;
0110 
0111     [[nodiscard]] AddresseeWrapper *contact();
0112     [[nodiscard]] qint64 collectionId() const;
0113     [[nodiscard]] Mode mode() const;
0114     void setMode(Mode mode);
0115     [[nodiscard]] bool isReadOnly() const;
0116     void setReadOnly(bool isReadOnly);
0117     void setCollectionId(qint64 collectionId);
0118 
0119     /**
0120      * Loads the @p contact into the editor.
0121      */
0122     Q_INVOKABLE void setItem(const Akonadi::Item &contact);
0123     Akonadi::Item item() const;
0124 
0125     /**
0126      * Save the contact from the editor back to the storage. And return error.
0127      * Need to connect to finished() signal, to keep time to Q_EMIT signal.
0128      */
0129     Q_INVOKABLE void saveContactInAddressBook();
0130 
0131     Q_INVOKABLE void fetchItem();
0132 
0133 Q_SIGNALS:
0134     /**
0135      * This signal is emitted when the @p contact has been saved back
0136      * to the storage.
0137      */
0138     void contactStored(const Akonadi::Item &contact);
0139 
0140     /**
0141      * This signal is emitted when an error occurred during the save.
0142      * @param errorMsg The error message.
0143      * @since 4.11
0144      */
0145     void errorOccured(const QString &errorMsg);
0146 
0147     /**
0148      * @brief finished
0149      * @since 4.11
0150      */
0151     void finished();
0152 
0153     void contactChanged();
0154     void modeChanged();
0155     void isReadOnlyChanged();
0156     void itemChanged();
0157     void collectionChanged();
0158     void itemChangedExternally();
0159 
0160 private:
0161     void itemFetchDone(KJob *job);
0162     void parentCollectionFetchDone(KJob *job);
0163     void storeDone(KJob *job);
0164     void loadContact(const KContacts::Addressee &contact, const ContactMetaData &metaData);
0165     void setupMonitor();
0166     void storeContact(KContacts::Addressee &contact, ContactMetaData &metaData) const;
0167 
0168     Akonadi::Item m_item;
0169     Akonadi::Collection m_defaultAddressBook;
0170     AddresseeWrapper *m_addressee = nullptr;
0171     Mode m_mode;
0172     bool m_readOnly = false;
0173     ContactMetaData m_contactMetaData;
0174     Akonadi::Monitor *m_monitor = nullptr;
0175 };