1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtNfc module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qqmlndefrecord.h"
41
42#include <QtCore/QMap>
43#include <QtCore/QRegularExpression>
44
45#include <QtCore/qglobalstatic.h>
46
47QT_BEGIN_NAMESPACE
48
49/*!
50 \class QQmlNdefRecord
51 \brief The QQmlNdefRecord class implements the NdefRecord type in QML.
52
53 \ingroup connectivity-nfc
54 \inmodule QtNfc
55 \since 5.2
56
57 \sa NdefRecord
58
59 The QQmlNdefRecord class is the base class for all NdefRecord types in QML. To
60 support a new NDEF record type in QML subclass this class and expose new properties, member
61 functions and signals appropriate for the new record type. The following must be done to
62 create a new NDEF record type in QML:
63
64 \list
65 \li The subclass must have a Q_OBJECT macro in its declaration.
66 \li The subclass must have an \l {Q_INVOKABLE}{invokable} constructor that takes a
67 QNdefRecord and a QObject pointer.
68 \li The subclass must be declared as an NDEF record by expanding the Q_DECLARE_NDEFRECORD()
69 macro in the implementation file of the subclass.
70 \li The subclass must be registered with QML.
71 \endlist
72
73 For example the declaration of such a class may look like the following.
74
75 \snippet foorecord.h Foo declaration
76
77 Within the implementation file the Q_DECLARE_NDEFRECORD() macro is expanded:
78
79 \snippet foorecord.cpp Declare foo record
80
81 Finially the application or plugin code calls qmlRegisterType():
82
83 \code
84 qmlRegisterType<QQmlNdefFooRecord>(uri, 1, 0, "NdefFooRecord");
85 \endcode
86*/
87
88/*!
89 \qmltype NdefRecord
90 \instantiates QQmlNdefRecord
91 \brief The NdefRecord type represents a record in an NDEF message.
92
93 \ingroup nfc-qml
94 \inqmlmodule QtNfc
95
96 \sa NdefFilter
97 \sa NearField
98
99 \sa QNdefRecord
100
101 The NdefRecord type is the base type for all NDEF record types in QML. It contains
102 a single property holding the type of record.
103
104 This class is not intended to be used directly, but extended from C++.
105
106 \sa QQmlNdefRecord
107*/
108
109/*!
110 \qmlproperty string NdefRecord::type
111
112 This property holds the type of the NDEF record.
113*/
114
115/*!
116 \qmlproperty enumeration NdefRecord::typeNameFormat
117
118 This property holds the TNF of the NDEF record.
119
120 \table
121 \header \li Property \li Description
122 \row \li \c NdefRecord.Empty
123 \li An empty NDEF record, the record does not contain a payload.
124 \row \li \c NdefRecord.NfcRtd
125 \li The NDEF record type is defined by an NFC RTD Specification.
126 \row \li \c NdefRecord.Mime
127 \li The NDEF record type follows the construct described in RFC 2046.
128 \row \li \c NdefRecord.Uri
129 \li The NDEF record type follows the construct described in RFC 3986.
130 \row \li \c NdefRecord.ExternalRtd
131 \li The NDEF record type follows the construct for external type names
132 described the NFC RTD Specification.
133 \endtable
134
135 \sa QNdefRecord::typeNameFormat()
136*/
137
138/*!
139 \qmlproperty string NdefRecord::record
140
141 This property holds the NDEF record.
142*/
143
144/*!
145 \fn void QQmlNdefRecord::typeChanged()
146
147 This signal is emitted when the record type changes.
148*/
149
150/*!
151 \property QQmlNdefRecord::record
152
153 This property hold the NDEF record that this class represents.
154*/
155
156/*!
157 \property QQmlNdefRecord::type
158
159 This property hold the type of the NDEF record.
160*/
161
162/*!
163 \property QQmlNdefRecord::typeNameFormat
164
165 This property hold the TNF of the NDEF record.
166*/
167
168/*!
169 \macro Q_DECLARE_NDEFRECORD(className, typeNameFormat, type)
170 \relates QQmlNdefRecord
171
172 This macro ensures that \a className is declared as the class implementing the NDEF record
173 identified by \a typeNameFormat and \a type.
174
175 This macro should be expanded in the implementation file for \a className.
176*/
177
178typedef QMap<QString, const QMetaObject *> NDefRecordTypesMap;
179Q_GLOBAL_STATIC(NDefRecordTypesMap, registeredNdefRecordTypes)
180
181class QQmlNdefRecordPrivate
182{
183public:
184 QNdefRecord record;
185};
186
187static QString urnForRecordType(QNdefRecord::TypeNameFormat typeNameFormat, const QByteArray &type)
188{
189 switch (typeNameFormat) {
190 case QNdefRecord::NfcRtd:
191 return QStringLiteral("urn:nfc:wkt:") + QString::fromLatin1(str: type);
192 case QNdefRecord::ExternalRtd:
193 return QStringLiteral("urn:nfc:ext:") + QString::fromLatin1(str: type);
194 case QNdefRecord::Mime:
195 return QStringLiteral("urn:nfc:mime:") + QString::fromLatin1(str: type);
196 default:
197 return QString();
198 }
199}
200
201/*!
202 \internal
203*/
204void qRegisterNdefRecordTypeHelper(const QMetaObject *metaObject,
205 QNdefRecord::TypeNameFormat typeNameFormat,
206 const QByteArray &type)
207{
208 registeredNdefRecordTypes()->insert(akey: urnForRecordType(typeNameFormat, type), avalue: metaObject);
209}
210
211/*!
212 \internal
213*/
214QQmlNdefRecord *qNewDeclarativeNdefRecordForNdefRecord(const QNdefRecord &record)
215{
216 const QString urn = urnForRecordType(typeNameFormat: record.typeNameFormat(), type: record.type());
217
218 const auto *rt = registeredNdefRecordTypes();
219
220 for (auto i = rt->cbegin(), end = rt->cend(); i != end; ++i) {
221 QRegularExpression rx(QRegularExpression::anchoredPattern(expression: i.key()));
222 if (!rx.match(subject: urn).hasMatch())
223 continue;
224
225 const QMetaObject *metaObject = i.value();
226 if (!metaObject)
227 continue;
228
229 return static_cast<QQmlNdefRecord *>(metaObject->newInstance(
230 Q_ARG(QNdefRecord, record), Q_ARG(QObject*, 0)));
231 }
232
233 return new QQmlNdefRecord(record);
234}
235
236/*!
237 Constructs a new empty QQmlNdefRecord with \a parent.
238*/
239QQmlNdefRecord::QQmlNdefRecord(QObject *parent)
240: QObject(parent), d_ptr(new QQmlNdefRecordPrivate)
241{
242}
243
244/*!
245 Constructs a new QQmlNdefRecord representing \a record. The parent of the newly
246 constructed object will be set to \a parent.
247*/
248QQmlNdefRecord::QQmlNdefRecord(const QNdefRecord &record, QObject *parent)
249: QObject(parent), d_ptr(new QQmlNdefRecordPrivate)
250{
251 d_ptr->record = record;
252}
253
254/*!
255 Destroys the QQmlNdefRecord instance.
256*/
257QQmlNdefRecord::~QQmlNdefRecord()
258{
259 delete d_ptr;
260}
261
262/*!
263 \enum QQmlNdefRecord::TypeNameFormat
264
265 This enum describes the type name format of an NDEF record. The values of this enum are according to
266 \l QNdefRecord::TypeNameFormat
267
268 \value Empty An empty NDEF record, the record does not contain a payload.
269 \value NfcRtd The NDEF record type is defined by an NFC RTD Specification.
270 \value Mime The NDEF record type follows the construct described in RFC 2046.
271 \value Uri The NDEF record type follows the construct described in RFC 3986.
272 \value ExternalRtd The NDEF record type follows the construct for external type names
273 described the NFC RTD Specification.
274 \value Unknown The NDEF record type is unknown.
275*/
276
277/*!
278 Returns the type of the record.
279
280 \sa QNdefRecord::setType(), QNdefRecord::type()
281*/
282QString QQmlNdefRecord::type() const
283{
284 Q_D(const QQmlNdefRecord);
285
286 return QLatin1String(d->record.type());
287}
288
289/*!
290 Sets the record type to \a newtype if it is not currently equal to \l type(); otherwise does
291 nothing. If the record type is set the typeChanged() signal will be emitted.
292
293 \sa QNdefRecord::setType(), QNdefRecord::type()
294*/
295void QQmlNdefRecord::setType(const QString &newtype)
296{
297 if (newtype == type())
298 return;
299
300 Q_D(QQmlNdefRecord);
301 d->record.setType(newtype.toUtf8());
302
303 emit typeChanged();
304}
305
306/*!
307 Sets the type name format of the NDEF record to \a newTypeNameFormat.
308*/
309void QQmlNdefRecord::setTypeNameFormat(QQmlNdefRecord::TypeNameFormat newTypeNameFormat)
310{
311 if (newTypeNameFormat == typeNameFormat())
312 return;
313
314 Q_D(QQmlNdefRecord);
315 d->record.setTypeNameFormat(static_cast<QNdefRecord::TypeNameFormat>(newTypeNameFormat));
316
317 emit typeNameFormatChanged();
318}
319
320/*!
321 \fn QQmlNdefRecord::TypeNameFormat QQmlNdefRecord::typeNameFormat() const
322
323 Returns the type name format of the NDEF record.
324*/
325QQmlNdefRecord::TypeNameFormat QQmlNdefRecord::typeNameFormat() const
326{
327 Q_D(const QQmlNdefRecord);
328 return static_cast<QQmlNdefRecord::TypeNameFormat>(d->record.typeNameFormat());
329}
330
331/*!
332 Returns a copy of the record.
333*/
334QNdefRecord QQmlNdefRecord::record() const
335{
336 Q_D(const QQmlNdefRecord);
337
338 return d->record;
339}
340
341/*!
342 Sets the record to \a record. If the record is set the recordChanged() signal will
343 be emitted.
344*/
345void QQmlNdefRecord::setRecord(const QNdefRecord &record)
346{
347 Q_D(QQmlNdefRecord);
348
349 if (d->record == record)
350 return;
351
352 d->record = record;
353 emit recordChanged();
354}
355
356QT_END_NAMESPACE
357

source code of qtconnectivity/src/nfc/qqmlndefrecord.cpp