File indexing completed on 2024-04-21 03:53:30

0001 /*
0002     This file is part of the KContacts framework.
0003     SPDX-FileCopyrightText: 2001 Cornelius Schumacher <schumacher@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "address.h"
0009 #include "addressformat.h"
0010 #include "addressformatter_p.h"
0011 
0012 #include "kcontacts_debug.h"
0013 #include <KConfig>
0014 #include <KCountry>
0015 #include <KLocalizedString>
0016 #include <krandom.h>
0017 
0018 #include <KConfigGroup>
0019 
0020 #include <QDataStream>
0021 #include <QSharedData>
0022 #include <QUrlQuery>
0023 
0024 using namespace KContacts;
0025 
0026 class Q_DECL_HIDDEN Address::Private : public QSharedData
0027 {
0028 public:
0029     Private()
0030         : mEmpty(true)
0031     {
0032         mId = KRandom::randomString(10);
0033     }
0034 
0035     Private(const Private &other)
0036         : QSharedData(other)
0037     {
0038         mEmpty = other.mEmpty;
0039         mId = other.mId;
0040         mType = other.mType;
0041 
0042         mPostOfficeBox = other.mPostOfficeBox;
0043         mExtended = other.mExtended;
0044         mStreet = other.mStreet;
0045         mLocality = other.mLocality;
0046         mRegion = other.mRegion;
0047         mPostalCode = other.mPostalCode;
0048         mCountry = other.mCountry;
0049         mLabel = other.mLabel;
0050     }
0051 
0052     bool mEmpty;
0053     QString mId;
0054     Type mType;
0055     Geo mGeo;
0056 
0057     QString mPostOfficeBox;
0058     QString mExtended;
0059     QString mStreet;
0060     QString mLocality;
0061     QString mRegion;
0062     QString mPostalCode;
0063     QString mCountry;
0064     QString mLabel;
0065 };
0066 
0067 Address::Address()
0068     : d(new Private)
0069 {
0070 }
0071 
0072 Address::Address(Type type)
0073     : d(new Private)
0074 {
0075     d->mType = type;
0076 }
0077 
0078 Address::Address(const Address &other)
0079     : d(other.d)
0080 {
0081 }
0082 
0083 Address::~Address()
0084 {
0085 }
0086 
0087 Address &Address::operator=(const Address &other)
0088 {
0089     if (this != &other) {
0090         d = other.d;
0091     }
0092 
0093     return *this;
0094 }
0095 
0096 bool Address::operator==(const Address &other) const
0097 {
0098     if (d->mId != other.d->mId) {
0099         return false;
0100     }
0101     if (d->mType != other.d->mType) {
0102         return false;
0103     }
0104     if (d->mPostOfficeBox != other.d->mPostOfficeBox) {
0105         return false;
0106     }
0107     if (d->mExtended != other.d->mExtended) {
0108         return false;
0109     }
0110     if (d->mStreet != other.d->mStreet) {
0111         return false;
0112     }
0113     if (d->mLocality != other.d->mLocality) {
0114         return false;
0115     }
0116     if (d->mRegion != other.d->mRegion) {
0117         return false;
0118     }
0119     if (d->mPostalCode != other.d->mPostalCode) {
0120         return false;
0121     }
0122     if (d->mCountry != other.d->mCountry) {
0123         return false;
0124     }
0125     if (d->mLabel != other.d->mLabel) {
0126         return false;
0127     }
0128 
0129     if (d->mGeo != other.d->mGeo) {
0130         return false;
0131     }
0132 
0133     return true;
0134 }
0135 
0136 bool Address::operator!=(const Address &a) const
0137 {
0138     return !(a == *this);
0139 }
0140 
0141 bool Address::isEmpty() const
0142 {
0143     return d->mEmpty;
0144 }
0145 
0146 void Address::clear()
0147 {
0148     *this = Address();
0149 }
0150 
0151 void Address::setId(const QString &id)
0152 {
0153     d->mEmpty = false;
0154     d->mId = id;
0155 }
0156 
0157 QString Address::id() const
0158 {
0159     return d->mId;
0160 }
0161 
0162 void Address::setType(Type type)
0163 {
0164     d->mEmpty = false;
0165     d->mType = type;
0166 }
0167 
0168 Address::Type Address::type() const
0169 {
0170     return d->mType;
0171 }
0172 
0173 QString Address::typeLabel(Type type)
0174 {
0175     QString label;
0176     const TypeList list = typeList();
0177 
0178     for (const auto typeFlag : list) {
0179         // these are actually flags
0180         const TypeFlag flag = static_cast<TypeFlag>(static_cast<int>(typeFlag));
0181         if (type & flag) {
0182             label.append(QLatin1Char('/') + typeFlagLabel(flag));
0183         }
0184     }
0185 
0186     // Remove the first '/'
0187     if (!label.isEmpty()) {
0188         label.remove(0, 1);
0189     }
0190 
0191     return label;
0192 }
0193 
0194 QString Address::typeLabel() const
0195 {
0196     QString label;
0197     const TypeList list = typeList();
0198 
0199     for (const auto f : list) {
0200         if ((type() & f) && (f != Pref)) {
0201             label.append(QLatin1Char('/') + typeLabel(f));
0202         }
0203     }
0204     // Remove the first '/'
0205     if (!label.isEmpty()) {
0206         label.remove(0, 1);
0207     }
0208     return label;
0209 }
0210 
0211 void Address::setPostOfficeBox(const QString &postOfficeBox)
0212 {
0213     d->mEmpty = false;
0214     d->mPostOfficeBox = postOfficeBox;
0215 }
0216 
0217 QString Address::postOfficeBox() const
0218 {
0219     return d->mPostOfficeBox;
0220 }
0221 
0222 QString Address::postOfficeBoxLabel()
0223 {
0224     return i18n("Post Office Box");
0225 }
0226 
0227 void Address::setExtended(const QString &extended)
0228 {
0229     d->mEmpty = false;
0230     d->mExtended = extended;
0231 }
0232 
0233 QString Address::extended() const
0234 {
0235     return d->mExtended;
0236 }
0237 
0238 QString Address::extendedLabel()
0239 {
0240     return i18n("Extended Address Information");
0241 }
0242 
0243 void Address::setStreet(const QString &street)
0244 {
0245     d->mEmpty = false;
0246     d->mStreet = street;
0247 }
0248 
0249 QString Address::street() const
0250 {
0251     return d->mStreet;
0252 }
0253 
0254 QString Address::streetLabel()
0255 {
0256     return i18n("Street");
0257 }
0258 
0259 void Address::setLocality(const QString &locality)
0260 {
0261     d->mEmpty = false;
0262     d->mLocality = locality;
0263 }
0264 
0265 QString Address::locality() const
0266 {
0267     return d->mLocality;
0268 }
0269 
0270 QString Address::localityLabel()
0271 {
0272     return i18n("Locality");
0273 }
0274 
0275 void Address::setRegion(const QString &region)
0276 {
0277     d->mEmpty = false;
0278     d->mRegion = region;
0279 }
0280 
0281 QString Address::region() const
0282 {
0283     return d->mRegion;
0284 }
0285 
0286 QString Address::regionLabel()
0287 {
0288     return i18n("Region");
0289 }
0290 
0291 void Address::setPostalCode(const QString &postalCode)
0292 {
0293     d->mEmpty = false;
0294     d->mPostalCode = postalCode;
0295 }
0296 
0297 QString Address::postalCode() const
0298 {
0299     return d->mPostalCode;
0300 }
0301 
0302 QString Address::postalCodeLabel()
0303 {
0304     return i18n("Postal Code");
0305 }
0306 
0307 void Address::setCountry(const QString &country)
0308 {
0309     d->mEmpty = false;
0310     d->mCountry = country;
0311 }
0312 
0313 QString Address::country() const
0314 {
0315     return d->mCountry;
0316 }
0317 
0318 QString Address::countryLabel()
0319 {
0320     return i18n("Country");
0321 }
0322 
0323 void Address::setLabel(const QString &label)
0324 {
0325     d->mEmpty = false;
0326     d->mLabel = label;
0327 }
0328 
0329 QString Address::label() const
0330 {
0331     return d->mLabel;
0332 }
0333 
0334 QString Address::labelLabel()
0335 {
0336     return i18n("Delivery Label");
0337 }
0338 
0339 Address::TypeList Address::typeList()
0340 {
0341     static TypeList list;
0342 
0343     if (list.isEmpty()) {
0344         list << Dom << Intl << Postal << Parcel << Home << Work << Pref;
0345     }
0346 
0347     return list;
0348 }
0349 
0350 QString Address::typeFlagLabel(TypeFlag type)
0351 {
0352     switch (type) {
0353     case Dom:
0354         return i18nc("Address is in home country", "Domestic");
0355     case Intl:
0356         return i18nc("Address is not in home country", "International");
0357     case Postal:
0358         return i18nc("Address for delivering letters", "Postal");
0359     case Parcel:
0360         return i18nc("Address for delivering packages", "Parcel");
0361     case Home:
0362         return i18nc("Home Address", "Home");
0363     case Work:
0364         return i18nc("Work Address", "Work");
0365     case Pref:
0366         return i18n("Preferred Address");
0367     }
0368     return i18nc("another type of address", "Other");
0369 }
0370 
0371 void Address::setGeo(const Geo &geo)
0372 {
0373     d->mEmpty = false;
0374     d->mGeo = geo;
0375 }
0376 
0377 Geo Address::geo() const
0378 {
0379     return d->mGeo;
0380 }
0381 
0382 QString Address::toString() const
0383 {
0384     QString str = QLatin1String("Address {\n");
0385     str += QStringLiteral("  IsEmpty: %1\n").arg(d->mEmpty ? QStringLiteral("true") : QStringLiteral("false"));
0386     str += QStringLiteral("  Id: %1\n").arg(d->mId);
0387     str += QStringLiteral("  Type: %1\n").arg(typeLabel(d->mType));
0388     str += QStringLiteral("  Post office box: %1\n").arg(d->mPostOfficeBox);
0389     str += QStringLiteral("  Extended: %1\n").arg(d->mExtended);
0390     str += QStringLiteral("  Street: %1\n").arg(d->mStreet);
0391     str += QStringLiteral("  Locality: %1\n").arg(d->mLocality);
0392     str += QStringLiteral("  Region: %1\n").arg(d->mRegion);
0393     str += QStringLiteral("  Postal code: %1\n").arg(d->mPostalCode);
0394     str += QStringLiteral("  Country: %1\n").arg(d->mCountry);
0395     str += QStringLiteral("  Label: %1\n").arg(d->mLabel);
0396     str += QStringLiteral("  Geo: %1\n").arg(d->mGeo.toString());
0397     str += QLatin1String("}\n");
0398 
0399     return str;
0400 }
0401 
0402 QString Address::formatted(AddressFormatStyle style, const QString &realName, const QString &orgaName) const
0403 {
0404     const auto formatPref = (orgaName.isEmpty() || style != AddressFormatStyle::Postal) ? AddressFormatPreference::Generic : AddressFormatPreference::Business;
0405     const auto format = AddressFormatRepository::formatForAddress(*this, formatPref);
0406     return AddressFormatter::format(*this, realName, orgaName, format, style);
0407 }
0408 
0409 QString Address::formattedPostalAddress() const
0410 {
0411     return formatted(AddressFormatStyle::Postal);
0412 }
0413 
0414 QUrl Address::geoUri() const
0415 {
0416     QUrl url;
0417     url.setScheme(QStringLiteral("geo"));
0418 
0419     if (geo().isValid()) {
0420         url.setPath(QString::number(geo().latitude()) + QLatin1Char(',') + QString::number(geo().longitude()));
0421         return url;
0422     }
0423 
0424     if (!isEmpty()) {
0425         url.setPath(QStringLiteral("0,0"));
0426         QUrlQuery query;
0427         query.addQueryItem(QStringLiteral("q"), formatted(KContacts::AddressFormatStyle::GeoUriQuery));
0428         url.setQuery(query);
0429         return url;
0430     }
0431 
0432     return {};
0433 }
0434 
0435 // clang-format off
0436 QDataStream &KContacts::operator<<(QDataStream &s, const Address &addr)
0437 {
0438     return s << addr.d->mId << (uint)addr.d->mType << addr.d->mPostOfficeBox
0439              << addr.d->mExtended << addr.d->mStreet << addr.d->mLocality
0440              << addr.d->mRegion << addr.d->mPostalCode << addr.d->mCountry
0441              << addr.d->mLabel << addr.d->mEmpty << addr.d->mGeo;
0442 }
0443 
0444 QDataStream &KContacts::operator>>(QDataStream &s, Address &addr)
0445 {
0446     uint type;
0447     s >> addr.d->mId >> type >> addr.d->mPostOfficeBox >> addr.d->mExtended
0448     >> addr.d->mStreet >> addr.d->mLocality >> addr.d->mRegion
0449     >> addr.d->mPostalCode >> addr.d->mCountry >> addr.d->mLabel
0450     >> addr.d->mEmpty >> addr.d->mGeo;
0451 
0452     addr.d->mType = Address::Type(type);
0453 
0454     return s;
0455 }
0456 // clang-format on
0457 
0458 #include "moc_address.cpp"