File indexing completed on 2024-05-12 05:21:34
0001 /* 0002 SPDX-FileCopyrightText: 2017-2021 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "field.h" 0008 #include "pass.h" 0009 #include "pass_p.h" 0010 0011 #include <QGuiApplication> 0012 #include <QJsonObject> 0013 0014 using namespace KPkPass; 0015 0016 namespace KPkPass 0017 { 0018 class FieldPrivate 0019 { 0020 public: 0021 const Pass *pass = nullptr; 0022 QJsonObject obj; 0023 }; 0024 } 0025 0026 Field::Field() 0027 : d(new FieldPrivate) 0028 { 0029 } 0030 0031 Field::Field(const Field &) = default; 0032 Field::Field(Field &&) = default; 0033 Field::~Field() = default; 0034 Field &Field::operator=(const Field &) = default; 0035 0036 Field::Field(const QJsonObject &obj, const Pass *pass) 0037 : d(new FieldPrivate) 0038 { 0039 d->pass = pass; 0040 d->obj = obj; 0041 } 0042 0043 QString Field::key() const 0044 { 0045 return d->obj.value(QLatin1StringView("key")).toString(); 0046 } 0047 0048 QString Field::label() const 0049 { 0050 if (d->pass) { 0051 return d->pass->d->message(d->obj.value(QLatin1StringView("label")).toString()); 0052 } 0053 return {}; 0054 } 0055 0056 QVariant Field::value() const 0057 { 0058 if (!d->pass) { 0059 return {}; 0060 } 0061 auto v = d->pass->d->message(d->obj.value(QLatin1StringView("attributedValue")).toString()); 0062 if (v.isEmpty()) { 0063 v = d->pass->d->message(d->obj.value(QLatin1StringView("value")).toString()); 0064 } 0065 0066 const auto dt = QDateTime::fromString(v, Qt::ISODate); 0067 if (dt.isValid()) { 0068 return dt; 0069 } 0070 0071 // TODO number detection 0072 return v; 0073 } 0074 0075 QString Field::valueDisplayString() const 0076 { 0077 const auto v = value(); 0078 // see 0079 // https://developer.apple.com/library/archive/documentation/UserExperience/Reference/PassKit_Bundle/Chapters/FieldDictionary.html#//apple_ref/doc/uid/TP40012026-CH4-SW6 0080 // however, real-world data doesn't strictly follow that, so we have to guess a bit here... 0081 if (v.userType() == QMetaType::QDateTime) { 0082 const auto dt = v.toDateTime(); 0083 auto fmt = QLocale::ShortFormat; 0084 const auto dtStyle = d->obj.value(QLatin1StringView("dateStyle")).toString(); 0085 if (dtStyle == QLatin1StringView("PKDateStyleLong") || dtStyle == QLatin1StringView("PKDateStyleFull")) { 0086 fmt = QLocale::LongFormat; 0087 } 0088 const auto timeStyle = d->obj.value(QLatin1StringView("timeStyle")).toString(); 0089 if (timeStyle == QLatin1StringView("PKDateStyleNone") || (timeStyle.isEmpty() && !dtStyle.isEmpty() && dt.time() == QTime(0, 0))) { 0090 return QLocale().toString(dt.date(), fmt); 0091 } 0092 0093 return QLocale().toString(dt, fmt); 0094 } 0095 0096 // TODO respect number formatting options 0097 return value().toString().trimmed(); 0098 } 0099 0100 QString Field::changeMessage() const 0101 { 0102 if (!d->pass) { 0103 return {}; 0104 } 0105 auto msg = d->pass->d->message(d->obj.value(QLatin1StringView("changeMessage")).toString()); 0106 msg.replace(QLatin1StringView("%@"), valueDisplayString()); 0107 return msg; 0108 } 0109 0110 Qt::Alignment Field::textAlignment() const 0111 { 0112 const auto alignStr = d->obj.value(QLatin1StringView("textAlignment")).toString(); 0113 if (alignStr == QLatin1StringView("PKTextAlignmentLeft")) { 0114 return Qt::AlignLeft; 0115 } else if (alignStr == QLatin1StringView("PKTextAlignmentCenter")) { 0116 return Qt::AlignHCenter; 0117 } else if (alignStr == QLatin1StringView("PKTextAlignmentRight")) { 0118 return Qt::AlignRight; 0119 } 0120 return QGuiApplication::layoutDirection() == Qt::LeftToRight ? Qt::AlignLeft : Qt::AlignRight; 0121 } 0122 0123 #include "moc_field.cpp"