File indexing completed on 2025-01-19 04:51:58

0001 /*
0002  *  Copyright (C) 2017 Michael Bohlender, <michael.bohlender@kdemail.net>
0003  *
0004  *  This program is free software; you can redistribute it and/or modify
0005  *  it under the terms of the GNU General Public License as published by
0006  *  the Free Software Foundation; either version 2 of the License, or
0007  *  (at your option) any later version.
0008  *
0009  *  This program is distributed in the hope that it will be useful,
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0012  *  GNU General Public License for more details.
0013  *
0014  *  You should have received a copy of the GNU General Public License along
0015  *  with this program; if not, write to the Free Software Foundation, Inc.,
0016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
0017  */
0018 
0019 #include "contactcontroller.h"
0020 
0021 #include <sink/applicationdomaintype.h>
0022 #include <sink/store.h>
0023 #include <sink/log.h>
0024 #include <KContacts/VCardConverter>
0025 
0026 using namespace Sink::ApplicationDomain;
0027 
0028 class MailsController : public Kube::ListPropertyController
0029 {
0030 public:
0031 
0032     MailsController()
0033         : Kube::ListPropertyController{{"email", "isMain"}}
0034     {
0035     }
0036 
0037     void set(const QStringList &list)
0038     {
0039         for (const auto &email: list) {
0040             add({{"email", email}, {"isMain", false}});
0041         }
0042     }
0043 
0044     QList<QString> get()
0045     {
0046         return getList<QString>("email");
0047     }
0048 };
0049 
0050 class PhonesController : public Kube::ListPropertyController
0051 {
0052 public:
0053 
0054     PhonesController()
0055         : Kube::ListPropertyController{{"number"}}
0056     {
0057     }
0058 
0059     void set(const QStringList &list)
0060     {
0061         for (const auto &number: list) {
0062             add({{"number", number}});
0063         }
0064     }
0065 
0066     QList<QString> get()
0067     {
0068         return getList<QString>("number");
0069     }
0070 };
0071 
0072 ContactController::ContactController()
0073     : Kube::Controller(),
0074     controller_mails{new MailsController},
0075     controller_phones(new PhonesController),
0076     action_save{new Kube::ControllerAction{this, &ContactController::save}}
0077 {
0078     updateSaveAction();
0079 }
0080 
0081 void ContactController::save()
0082 {
0083     using namespace Sink;
0084     using namespace Sink::ApplicationDomain;
0085 
0086     const auto addressbook = getAddressbook();
0087     if (!addressbook) {
0088         qWarning() << "No addressbook selected";
0089         return;
0090     }
0091 
0092     auto populateAddressee = [this] (KContacts::Addressee &addressee) {
0093         addressee.setGivenName(getFirstName());
0094         addressee.setFamilyName(getLastName());
0095         addressee.setFormattedName(getFirstName() + " " + getLastName());
0096         addressee.setEmails(static_cast<MailsController*>(mailsController())->get());
0097         //TODO phone numbers, addresses, ...
0098     };
0099 
0100     if (auto c = mContact.value<Sink::ApplicationDomain::Contact::Ptr>()) {
0101         Contact contact = *c;
0102 
0103         //Apply the changed properties on top of what's existing
0104         KContacts::Addressee addressee = KContacts::VCardConverter{}.parseVCard(contact.getVcard());
0105         populateAddressee(addressee);
0106 
0107         contact.setVcard(KContacts::VCardConverter{}.createVCard(addressee, KContacts::VCardConverter::v3_0));
0108         contact.setAddressbook(*addressbook);
0109 
0110         auto job = Store::modify(contact)
0111             .then([&] (const KAsync::Error &error) {
0112                 if (error) {
0113                     SinkWarning() << "Failed to save the contact: " << error;
0114                 }
0115                 emit done();
0116             });
0117 
0118         run(job);
0119 
0120     } else {
0121         Contact contact(addressbook->resourceInstanceIdentifier());
0122 
0123         KContacts::Addressee addressee;
0124         populateAddressee(addressee);
0125 
0126         contact.setVcard(KContacts::VCardConverter{}.createVCard(addressee, KContacts::VCardConverter::v3_0));
0127         contact.setAddressbook(*addressbook);
0128 
0129         auto job = Store::create(contact)
0130             .then([&] (const KAsync::Error &error) {
0131                 if (error) {
0132                     SinkWarning() << "Failed to save the contact: " << error;
0133                 }
0134                 emit done();
0135             });
0136 
0137         run(job);
0138     }
0139 }
0140 
0141 void ContactController::updateSaveAction()
0142 {
0143     saveAction()->setEnabled(!getFirstName().isEmpty());
0144 }
0145 
0146 void ContactController::loadContact(const QVariant &variant)
0147 {
0148     using namespace Sink;
0149 
0150     mContact = variant;
0151     if (auto c = variant.value<ApplicationDomain::Contact::Ptr>()) {
0152 
0153         setAddressbook(ApplicationDomainType::Ptr::create(ApplicationDomainType::createEntity<ApplicationDomain::Addressbook>(c->resourceInstanceIdentifier(), c->getAddressbook())));
0154         const auto addressee = KContacts::VCardConverter{}.parseVCard(c->getVcard());
0155 
0156         setName(c->getFn());
0157         setFirstName(addressee.givenName());
0158         setLastName(addressee.familyName());
0159 
0160         static_cast<MailsController*>(mailsController())->set(addressee.emails());
0161 
0162         QStringList numbers;
0163         for (const auto &n : addressee.phoneNumbers()) {
0164             numbers << n.number();
0165         }
0166         static_cast<PhonesController*>(phonesController())->set(numbers);
0167 
0168         for(const auto &a :addressee.addresses()) {
0169             setStreet(a.street());
0170             setCity(a.locality());
0171             setCountry(a.country());
0172             break;
0173         }
0174         setCompany(addressee.organization());
0175         setJobTitle(addressee.role());
0176         setImageData(addressee.photo().rawData());
0177     }
0178 }
0179 
0180 void ContactController::remove()
0181 {
0182     if (auto c = mContact.value<Sink::ApplicationDomain::Contact::Ptr>()) {
0183         run(Sink::Store::remove(*c));
0184     }
0185 }
0186 
0187 QVariant ContactController::contact() const
0188 {
0189     return mContact;
0190 }