diff --git a/autotests/resourcelocatorurltest.cpp b/autotests/resourcelocatorurltest.cpp --- a/autotests/resourcelocatorurltest.cpp +++ b/autotests/resourcelocatorurltest.cpp @@ -104,18 +104,25 @@ "VERSION:3.0\n" "N:LastName;FirstName;;;\n" "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n" - "URL;PREF=1:https://firsturl\n" - "URL;PREF=1:https://sherlockholmes.com/calendar/sherlockholmes\n" + "URL;PREF=1;TYPE=HOME:https://firsturl\n" + "URL;TYPE=WORK,PREF:https://sherlockholmes.com/calendar/sherlockholmes\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); QCOMPARE(lst.at(0).extraUrlList().count(), 2); - const ResourceLocatorUrl calurl = lst.at(0).extraUrlList().at(0); + auto calurl = lst.at(0).extraUrlList().at(0); QCOMPARE(calurl.url(), QUrl(QStringLiteral("https://firsturl"))); + QVERIFY(calurl.isPreferred()); + QCOMPARE(calurl.type(), KContacts::ResourceLocatorUrl::Home); + QVERIFY(!calurl.parameters().isEmpty()); + calurl = lst.at(0).extraUrlList().at(1); + QCOMPARE(calurl.url(), QUrl(QStringLiteral("https://sherlockholmes.com/calendar/sherlockholmes"))); + QVERIFY(calurl.isPreferred()); + QCOMPARE(calurl.type(), KContacts::ResourceLocatorUrl::Work); QVERIFY(!calurl.parameters().isEmpty()); } @@ -204,6 +211,8 @@ url.setUrl(QUrl(QStringLiteral("https://foo.kde.org"))); QMap params2; url.setParameters(params2); + url.setType(ResourceLocatorUrl::Work); + url.setPreferred(true); addr.insertExtraUrl(url); lst << addr; KContacts::VCardTool vcard; @@ -216,7 +225,7 @@ "UID:testuid\r\n" "URL:https://www.kde.org\r\n" "URL;FOO2=bla2,blo2:https://sherlockholmes.com/calendar/sherlockholmes\r\n" - "URL:https://foo.kde.org\r\n" + "URL;TYPE=WORK,PREF:https://foo.kde.org\r\n" "END:VCARD\r\n\r\n"); QCOMPARE(ba, expected); diff --git a/src/resourcelocatorurl.h b/src/resourcelocatorurl.h --- a/src/resourcelocatorurl.h +++ b/src/resourcelocatorurl.h @@ -42,6 +42,8 @@ Q_GADGET Q_PROPERTY(QUrl url READ url WRITE setUrl) Q_PROPERTY(bool isValid READ isValid) + Q_PROPERTY(Type type READ type WRITE setType) + Q_PROPERTY(bool isPreferred READ isPreferred WRITE setPreferred) public: @@ -52,11 +54,46 @@ typedef QVector List; + /** URL types. + * @since 5.12 + */ + enum TypeFlag { + Unknown = 0, /**< No or unknown URL type is set. */ + Home = 1, /**< Personal website. */ + Work = 2, /**< Work website. */ + Profile = 4, /**< Profile website. */ + Other = 8 /**< Other websie. */ + }; + Q_DECLARE_FLAGS(Type, TypeFlag) + Q_FLAG(Type) + Q_REQUIRED_RESULT bool isValid() const; void setUrl(const QUrl &url); Q_REQUIRED_RESULT QUrl url() const; + /** + * Returns the type of the URL. + * @since 5.12 + */ + Type type() const; + /** + * Sets the URL type. + * @since 5.12 + */ + void setType(Type type); + + /** + * Returns whether this is the preferred website. + * @since 5.12 + */ + bool isPreferred() const; + /** + * Sets that this is the preferred website. + * @since 5.12 + */ + void setPreferred(bool preferred); + void setParameters(const QMap ¶ms); Q_REQUIRED_RESULT QMap parameters() const; @@ -71,6 +108,8 @@ QSharedDataPointer d; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(ResourceLocatorUrl::Type) + KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const ResourceLocatorUrl &object); KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, ResourceLocatorUrl &object); diff --git a/src/resourcelocatorurl.cpp b/src/resourcelocatorurl.cpp --- a/src/resourcelocatorurl.cpp +++ b/src/resourcelocatorurl.cpp @@ -57,6 +57,89 @@ { } +struct url_type_name +{ + const char* name; + ResourceLocatorUrl::Type type; +}; + +static const url_type_name url_type_names[] = { + { "HOME", ResourceLocatorUrl::Home }, + { "WORK", ResourceLocatorUrl::Work }, + { "OTHER", ResourceLocatorUrl::Other }, + { "PROFILE", ResourceLocatorUrl::Profile } +}; + +ResourceLocatorUrl::Type ResourceLocatorUrl::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(url_type_names), std::end(url_type_names), [s](const url_type_name &t) { + return QLatin1String(t.name) == s; + }); + if (it != std::end(url_type_names)) { + type |= (*it).type; + } + } + return type; +} + +void ResourceLocatorUrl::setType(ResourceLocatorUrl::Type type) +{ + const auto oldType = this->type(); + + auto types = d->parameters.value(QLatin1String("type")); + for (const auto &t : url_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 ResourceLocatorUrl::isPreferred() const +{ + auto it = d->parameters.constFind(QLatin1String("pref")); + if (it != d->parameters.end() && !it.value().isEmpty()) { + return it.value().at(0) == QLatin1String("1"); + } + + it = d->parameters.constFind(QLatin1String("type")); + if (it != d->parameters.end()) { + return it.value().contains(QLatin1String("PREF"), Qt::CaseInsensitive); + } + + return false; +} + +void ResourceLocatorUrl::setPreferred(bool preferred) +{ + if (preferred == isPreferred()) { + return; + } + + auto types = d->parameters.value(QLatin1String("type")); + if (!preferred) { + d->parameters.remove(QLatin1String("pref")); + types.removeAll(QLatin1String("PREF")); + } else { + types.push_back(QLatin1String("PREF")); + } + d->parameters.insert(QLatin1String("type"), types); +} + QMap ResourceLocatorUrl::parameters() const { return d->parameters;