diff --git a/autotests/emailtest.cpp b/autotests/emailtest.cpp index acf51286..df7fb9ac 100644 --- a/autotests/emailtest.cpp +++ b/autotests/emailtest.cpp @@ -1,185 +1,208 @@ /* This file is part of the KContacts framework. Copyright (C) 2015-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "emailtest.h" #include "email.h" #include #include "vcardtool_p.h" EmailTest::EmailTest(QObject *parent) : QObject(parent) { } EmailTest::~EmailTest() { } void EmailTest::shouldHaveDefaultValue() { KContacts::Email email; QVERIFY(!email.isValid()); QVERIFY(email.mail().isEmpty()); QVERIFY(email.parameters().isEmpty()); } void EmailTest::shouldAssignValue() { const QString mail(QStringLiteral("foo@kde.org")); QMap params; params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1")); params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2")); KContacts::Email email(mail); email.setParameters(params); QVERIFY(email.isValid()); QVERIFY(!email.mail().isEmpty()); QCOMPARE(email.mail(), mail); QVERIFY(!email.parameters().isEmpty()); QCOMPARE(email.parameters(), params); } void EmailTest::shouldAssignExternal() { KContacts::Email email; const QString mail(QStringLiteral("foo@kde.org")); email.setEmail(mail); QVERIFY(email.isValid()); QVERIFY(!email.mail().isEmpty()); QCOMPARE(email.mail(), mail); } void EmailTest::shouldSerialized() { KContacts::Email email; KContacts::Email result; const QString mail(QStringLiteral("foo@kde.org")); email.setEmail(mail); QMap params; params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1")); params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2")); email.setParameters(params); QByteArray data; QDataStream s(&data, QIODevice::WriteOnly); s << email; QDataStream t(&data, QIODevice::ReadOnly); t >> result; QVERIFY(email == result); } void EmailTest::shouldEqualEmail() { KContacts::Email email; KContacts::Email result; const QString mail(QStringLiteral("foo@kde.org")); email.setEmail(mail); QMap params; params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1")); params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2")); email.setParameters(params); result = email; QVERIFY(email == result); } void EmailTest::shouldParseEmailVCard() { QByteArray vcarddata("BEGIN:VCARD\n" "VERSION:3.0\n" "EMAIL;TYPE=HOME,PREF;X-EVOLUTION-UI-SLOT=2:foo@foo.com\n" "N:LastName;FirstName;;;\n" "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n" "REV:2015-03-14T09:24:45+00:00\n" "FN:FirstName LastName\n" "END:VCARD\n"); KContacts::VCardTool vcard; const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata); QCOMPARE(lst.count(), 1); QVERIFY(!lst.at(0).emailList().isEmpty()); QCOMPARE(lst.at(0).emailList().count(), 1); KContacts::Email email = lst.at(0).emailList().at(0); QCOMPARE(email.mail(), QStringLiteral("foo@foo.com")); QCOMPARE(email.parameters().count(), 2); } void EmailTest::shouldParseEmailVCardWithMultiEmails() { QByteArray vcarddata("BEGIN:VCARD\n" "VERSION:3.0\n" - "EMAIL;TYPE=HOME,PREF;X-EVOLUTION-UI-SLOT=2:foo@foo.com\n" + "EMAIL;TYPE=WORK;X-EVOLUTION-UI-SLOT=2:foo@foo.com\n" "EMAIL;TYPE=HOME,PREF;X-EVOLUTION-UI-SLOT=2:bla@bla.com\n" "N:LastName;FirstName;;;\n" "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n" "REV:2015-03-14T09:24:45+00:00\n" "FN:FirstName LastName\n" "END:VCARD\n"); KContacts::VCardTool vcard; const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata); QCOMPARE(lst.count(), 1); QVERIFY(!lst.at(0).emailList().isEmpty()); QCOMPARE(lst.at(0).emailList().count(), 2); KContacts::Email email = lst.at(0).emailList().at(0); QCOMPARE(email.mail(), QStringLiteral("bla@bla.com")); + QCOMPARE(email.type(), KContacts::Email::Home | KContacts::Email::Preferred); + QVERIFY(email.isPreferred()); email = lst.at(0).emailList().at(1); QCOMPARE(email.mail(), QStringLiteral("foo@foo.com")); + QCOMPARE(email.type(), KContacts::Email::Work); + QVERIFY(!email.isPreferred()); QCOMPARE(email.parameters().count(), 2); } void EmailTest::shouldParseEmailVCardWithoutEmail() { QByteArray vcarddata("BEGIN:VCARD\n" "VERSION:3.0\n" "N:LastName;FirstName;;;\n" "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n" "REV:2015-03-14T09:24:45+00:00\n" "FN:FirstName LastName\n" "END:VCARD\n"); KContacts::VCardTool vcard; const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata); QCOMPARE(lst.count(), 1); QVERIFY(lst.at(0).emailList().isEmpty()); } void EmailTest::shouldExportVcard() { KContacts::AddresseeList lst; KContacts::Addressee addr; addr.setEmails(QStringList() << QStringLiteral("foo@kde.org") << QStringLiteral("bla@kde.org")); addr.setUid(QStringLiteral("testuid")); lst << addr; KContacts::VCardTool vcard; - const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0); + QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0); QByteArray expected("BEGIN:VCARD\r\n" "VERSION:4.0\r\n" "EMAIL:foo@kde.org\r\n" "EMAIL:bla@kde.org\r\n" "N:;;;;\r\n" "UID:testuid\r\n" "END:VCARD\r\n\r\n"); QCOMPARE(ba, expected); + + KContacts::Addressee addr2; + addr2.setUid(QStringLiteral("testuid")); + KContacts::Email email1, email2; + email1.setEmail(QStringLiteral("foo@kde.org")); + email1.setType(KContacts::Email::Work | KContacts::Email::Preferred); + email2.setEmail(QStringLiteral("bla@kde.org")); + email2.setType(KContacts::Email::Home); + addr2.setEmailList({email1, email2}); + ba = vcard.exportVCards({addr2}, KContacts::VCard::v4_0); + QByteArray expected2("BEGIN:VCARD\r\n" + "VERSION:4.0\r\n" + "EMAIL;TYPE=WORK,PREF:foo@kde.org\r\n" + "EMAIL;TYPE=HOME:bla@kde.org\r\n" + "N:;;;;\r\n" + "UID:testuid\r\n" + "END:VCARD\r\n\r\n"); + + QCOMPARE(ba, expected2); } QTEST_MAIN(EmailTest) diff --git a/src/email.cpp b/src/email.cpp index 5d22b405..52f5a51b 100644 --- a/src/email.cpp +++ b/src/email.cpp @@ -1,138 +1,195 @@ /* This file is part of the KContacts framework. Copyright (C) 2015-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "email.h" #include #include #include using namespace KContacts; class Q_DECL_HIDDEN Email::Private : public QSharedData { public: Private() { } Private(const Private &other) : QSharedData(other) { parameters = other.parameters; mail = other.mail; } QMap parameters; QString mail; }; Email::Email() : d(new Private) { } Email::Email(const QString &mail) : d(new Private) { d->mail = mail; } Email::Email(const Email &other) : d(other.d) { } Email::~Email() { } QMap Email::parameters() const { return d->parameters; } bool Email::operator==(const Email &other) const { return (d->parameters == other.parameters()) && (d->mail == other.mail()); } bool Email::operator!=(const Email &other) const { return !(other == *this); } Email &Email::operator=(const Email &other) { if (this != &other) { d = other.d; } return *this; } QString Email::toString() const { QString str = QLatin1String("Email {\n"); str += QStringLiteral(" mail: %1\n").arg(d->mail); if (!d->parameters.isEmpty()) { QString param; QMap::const_iterator it = d->parameters.constBegin(); const QMap::const_iterator end = d->parameters.constEnd(); while (it != end) { param += QStringLiteral("%1 %2").arg(it.key(), it.value().join(QLatin1Char(','))); ++it; } str += QStringLiteral(" parameters: %1\n").arg(param); } str += QLatin1String("}\n"); return str; } void Email::setParameters(const QMap ¶ms) { d->parameters = params; } void Email::setEmail(const QString &mail) { d->mail = mail; } QString Email::mail() const { return d->mail; } bool Email::isValid() const { return !d->mail.isEmpty(); } +struct email_type_name +{ + const char* name; + Email::Type type; +}; + +static const email_type_name email_type_names[] = { + { "HOME", Email::Home }, + { "WORK", Email::Work }, + { "OTHER", Email::Other }, + { "PREF", Email::Preferred } +}; + +Email::Type KContacts::Email::type() const +{ + const auto it = d->parameters.constFind(QLatin1String("type")); + if (it == d->parameters.end()) { + return Unknown; + } + + Type type = Unknown; + for (const auto &s : it.value()) { + const auto it = std::find_if(std::begin(email_type_names), std::end(email_type_names), [s](const email_type_name &t) { + return QLatin1String(t.name) == s; + }); + if (it != std::end(email_type_names)) { + type |= (*it).type; + } + } + return type; +} + +void Email::setType(Type type) +{ + const auto oldType = this->type(); + + auto types = d->parameters.value(QLatin1String("type")); + for (const auto &t : email_type_names) { + if (((type ^ oldType) & t.type) == 0) { + continue; // no change + } + + if (type & t.type) { + types.push_back(QLatin1String(t.name)); + } else { + types.removeAll(QLatin1String(t.name)); + } + } + + d->parameters.insert(QLatin1String("type"), types); +} + +bool Email::isPreferred() const +{ + return type() & Preferred; +} + QDataStream &KContacts::operator<<(QDataStream &s, const Email &email) { return s << email.d->parameters << email.d->mail; } QDataStream &KContacts::operator>>(QDataStream &s, Email &email) { s >> email.d->parameters >> email.d->mail; return s; } diff --git a/src/email.h b/src/email.h index bc633ec5..4e760855 100644 --- a/src/email.h +++ b/src/email.h @@ -1,82 +1,115 @@ /* This file is part of the KContacts framework. Copyright (C) 2015-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef EMAIL_H #define EMAIL_H #include "kcontacts_export.h" #include #include #include #include /** @short Class that holds a Email for a contact. * @since 4.14.5 */ namespace KContacts { class KCONTACTS_EXPORT Email { friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const Email &); friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, Email &); Q_GADGET Q_PROPERTY(QString email READ mail WRITE setEmail) Q_PROPERTY(bool isValid READ isValid) + Q_PROPERTY(Type type READ type WRITE setType) + Q_PROPERTY(bool isPreferred) public: /** * Creates an empty email object. */ Email(); Email(const Email &other); Email(const QString &mail); ~Email(); typedef QVector List; + /** Email types. */ + enum TypeFlag { + Unknown = 0, /**< No or unknown email type is set. */ + Home = 1, /**< Personal email. */ + Work = 2, /**< Work email. */ + Other = 4, /**< Other email. */ + Preferred = 8 /**< Preferred email address. */ + }; + + Q_DECLARE_FLAGS(Type, TypeFlag) + Q_FLAG(Type) + void setEmail(const QString &mail); Q_REQUIRED_RESULT QString mail() const; Q_REQUIRED_RESULT bool isValid() const; + /** + * Returns the type of the email. + * @since 5.12 + */ + Type type() const; + /** + * Sets the email type. + * @since 5.12 + */ + void setType(Type type); + + /** + * Returns whether this is the preferred email address. + * @since 5.12 + */ + bool isPreferred() const; + void setParameters(const QMap ¶ms); Q_REQUIRED_RESULT QMap parameters() const; Q_REQUIRED_RESULT bool operator==(const Email &other) const; Q_REQUIRED_RESULT bool operator!=(const Email &other) const; Email &operator=(const Email &other); Q_REQUIRED_RESULT QString toString() const; private: class Private; QSharedDataPointer d; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(Email::Type) + KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const Email &object); KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, Email &object); } Q_DECLARE_METATYPE(KContacts::Email) Q_DECLARE_TYPEINFO(KContacts::Email, Q_MOVABLE_TYPE); #endif // EMAIL_H