| /*************************************************************************** |
| ** |
| ** Copyright (C) 2016 - 2012 Research In Motion |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the QtNfc module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include <qndefnfcsmartposterrecord.h> |
| #include "qndefnfcsmartposterrecord_p.h" |
| #include <qndefmessage.h> |
| |
| #include <QtCore/QString> |
| #include <QtCore/QStringList> |
| #include <QtCore/QUrl> |
| |
| QT_BEGIN_NAMESPACE |
| |
| /*! |
| \class QNdefNfcSmartPosterRecord |
| \brief The QNdefNfcSmartPosterRecord class provides an NFC RTD-SmartPoster. |
| |
| \ingroup connectivity-nfc |
| \inmodule QtNfc |
| \since Qt 5.2 |
| |
| RTD-SmartPoster encapsulates a Smart Poster. |
| */ |
| |
| /*! |
| \enum QNdefNfcSmartPosterRecord::Action |
| |
| This enum describes the course of action that a device should take with the content. |
| |
| \value UnspecifiedAction The action is not defined. |
| \value DoAction Do the action (send the SMS, launch the browser, make the telephone call). |
| \value SaveAction Save for later (store the SMS in INBOX, put the URI in a bookmark, save the telephone number in contacts). |
| \value EditAction Open for editing (open an SMS in the SMS editor, open the URI in a URI editor, open the telephone number for editing). |
| */ |
| |
| /*! |
| Constructs a new empty smart poster. |
| */ |
| QNdefNfcSmartPosterRecord::QNdefNfcSmartPosterRecord() |
| : QNdefRecord(QNdefRecord::NfcRtd, "Sp"), |
| d(new QNdefNfcSmartPosterRecordPrivate) |
| { |
| } |
| |
| /*! |
| Constructs a new smart poster that is a copy of \a other. |
| */ |
| QNdefNfcSmartPosterRecord::QNdefNfcSmartPosterRecord(const QNdefRecord &other) |
| : QNdefRecord(other, QNdefRecord::NfcRtd, "Sp"), |
| d(new QNdefNfcSmartPosterRecordPrivate) |
| { |
| // Need to set payload again to create internal structure |
| setPayload(other.payload()); |
| } |
| |
| /*! |
| Constructs a new smart poster that is a copy of \a other. |
| */ |
| QNdefNfcSmartPosterRecord::QNdefNfcSmartPosterRecord(const QNdefNfcSmartPosterRecord &other) |
| : QNdefRecord(other, QNdefRecord::NfcRtd, "Sp"), d(other.d) |
| { |
| } |
| |
| /*! |
| Assigns the \a other smart poster record to this record and returns a reference to |
| this record. |
| */ |
| QNdefNfcSmartPosterRecord &QNdefNfcSmartPosterRecord::operator=(const QNdefNfcSmartPosterRecord &other) |
| { |
| if (this != &other) |
| d = other.d; |
| |
| return *this; |
| } |
| |
| /*! |
| Destroys the smart poster. |
| */ |
| QNdefNfcSmartPosterRecord::~QNdefNfcSmartPosterRecord() |
| { |
| } |
| |
| void QNdefNfcSmartPosterRecord::cleanup() |
| { |
| if (d) { |
| // Clean-up existing internal structure |
| d->m_titleList.clear(); |
| if (d->m_uri) delete d->m_uri; |
| if (d->m_action) delete d->m_action; |
| d->m_iconList.clear(); |
| if (d->m_size) delete d->m_size; |
| if (d->m_type) delete d->m_type; |
| } |
| } |
| |
| /*! |
| \internal |
| Sets the payload of the NDEF record to \a payload |
| */ |
| void QNdefNfcSmartPosterRecord::setPayload(const QByteArray &payload) |
| { |
| QNdefRecord::setPayload(payload); |
| |
| cleanup(); |
| |
| if (!payload.isEmpty()) { |
| // Create new structure |
| const QNdefMessage message = QNdefMessage::fromByteArray(payload); |
| |
| // Iterate through all the records contained in the payload's message. |
| for (const QNdefRecord& record : message) { |
| // Title |
| if (record.isRecordType<QNdefNfcTextRecord>()) { |
| addTitleInternal(record); |
| } |
| |
| // URI |
| else if (record.isRecordType<QNdefNfcUriRecord>()) { |
| d->m_uri = new QNdefNfcUriRecord(record); |
| } |
| |
| // Action |
| else if (record.isRecordType<QNdefNfcActRecord>()) { |
| d->m_action = new QNdefNfcActRecord(record); |
| } |
| |
| // Icon |
| else if (record.isRecordType<QNdefNfcIconRecord>()) { |
| addIconInternal(record); |
| } |
| |
| // Size |
| else if (record.isRecordType<QNdefNfcSizeRecord>()) { |
| d->m_size = new QNdefNfcSizeRecord(record); |
| } |
| |
| // Type |
| else if (record.isRecordType<QNdefNfcTypeRecord>()) { |
| d->m_type = new QNdefNfcTypeRecord(record); |
| } |
| } |
| } |
| } |
| |
| void QNdefNfcSmartPosterRecord::convertToPayload() |
| { |
| QNdefMessage message; |
| |
| // Title |
| for (int t=0; t<titleCount(); t++) |
| message.append(titleRecord(t)); |
| |
| // URI |
| if (d->m_uri) |
| message.append(*(d->m_uri)); |
| |
| // Action |
| if (d->m_action) |
| message.append(*(d->m_action)); |
| |
| // Icon |
| for (int i=0; i<iconCount(); i++) |
| message.append(iconRecord(i)); |
| |
| // Size |
| if (d->m_size) |
| message.append(*(d->m_size)); |
| |
| // Type |
| if (d->m_type) |
| message.append(*(d->m_type)); |
| |
| QNdefRecord::setPayload(message.toByteArray()); |
| } |
| |
| /*! |
| Returns true if the smart poster contains a title record using locale \a locale. If \a locale |
| is empty then true is returned if the smart poster contains at least one title record. In all |
| cases false is returned. |
| */ |
| bool QNdefNfcSmartPosterRecord::hasTitle(const QString &locale) const |
| { |
| for (int i = 0; i < d->m_titleList.length(); ++i) { |
| const QNdefNfcTextRecord &text = d->m_titleList[i]; |
| |
| if (locale.isEmpty() || text.locale() == locale) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /*! |
| Returns true if the smart poster contains an action record, otherwise false. |
| */ |
| bool QNdefNfcSmartPosterRecord::hasAction() const |
| { |
| return d->m_action != 0; |
| } |
| |
| /*! |
| Returns true if the smart poster contains an icon record using type \a mimetype. |
| If \a mimetype is empty then true is returned if the smart poster contains at least one icon record. |
| In all other cases false is returned. |
| */ |
| bool QNdefNfcSmartPosterRecord::hasIcon(const QByteArray &mimetype) const |
| { |
| for (int i = 0; i < d->m_iconList.length(); ++i) { |
| const QNdefNfcIconRecord &icon = d->m_iconList[i]; |
| |
| if (mimetype.isEmpty() || icon.type() == mimetype) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /*! |
| Returns true if the smart poster contains a size record, otherwise false. |
| */ |
| bool QNdefNfcSmartPosterRecord::hasSize() const |
| { |
| return d->m_size != 0; |
| } |
| |
| /*! |
| Returns true if the smart poster contains a type record, otherwise false. |
| */ |
| bool QNdefNfcSmartPosterRecord::hasTypeInfo() const |
| { |
| return d->m_type != 0; |
| } |
| |
| /*! |
| Returns the number of title records contained inside the smart poster. |
| */ |
| int QNdefNfcSmartPosterRecord::titleCount() const |
| { |
| return d->m_titleList.length(); |
| } |
| |
| /*! |
| Returns the title record corresponding to the index \a index inside the smart poster, where \a index is a value between 0 and titleCount() - 1. Values outside of this range return an empty record. |
| */ |
| QNdefNfcTextRecord QNdefNfcSmartPosterRecord::titleRecord(const int index) const |
| { |
| if (index >= 0 && index < d->m_titleList.length()) |
| return d->m_titleList[index]; |
| |
| return QNdefNfcTextRecord(); |
| } |
| |
| /*! |
| Returns the title record text associated with locale \a locale if available. If \a locale |
| is empty then the title text of the first available record is returned. In all other |
| cases an empty string is returned. |
| */ |
| QString QNdefNfcSmartPosterRecord::title(const QString &locale) const |
| { |
| for (int i = 0; i < d->m_titleList.length(); ++i) { |
| const QNdefNfcTextRecord &text = d->m_titleList[i]; |
| |
| if (locale.isEmpty() || text.locale() == locale) |
| return text.text(); |
| } |
| |
| return QString(); |
| } |
| |
| /*! |
| Returns a copy of all title records inside the smart poster. |
| */ |
| QList<QNdefNfcTextRecord> QNdefNfcSmartPosterRecord::titleRecords() const |
| { |
| return d->m_titleList; |
| } |
| |
| /*! |
| Attempts to add a title record \a text to the smart poster. If the smart poster does not already |
| contain a title record with the same locale as title record \a text, then the title record is added |
| and the function returns true. Otherwise false is returned. |
| */ |
| bool QNdefNfcSmartPosterRecord::addTitle(const QNdefNfcTextRecord &text) |
| { |
| bool status = addTitleInternal(text); |
| |
| // Convert to payload |
| convertToPayload(); |
| |
| return status; |
| } |
| |
| bool QNdefNfcSmartPosterRecord::addTitleInternal(const QNdefNfcTextRecord &text) |
| { |
| for (int i = 0; i < d->m_titleList.length(); ++i) { |
| const QNdefNfcTextRecord &rec = d->m_titleList[i]; |
| |
| if (rec.locale() == text.locale()) |
| return false; |
| } |
| |
| d->m_titleList.append(text); |
| return true; |
| } |
| |
| /*! |
| Attempts to add a new title record with title \a text, locale \a locale and encoding \a encoding. |
| If the smart poster does not already contain a title record with locale \a locale, then the title record |
| is added and the function returns true. Otherwise false is returned. |
| */ |
| bool QNdefNfcSmartPosterRecord::addTitle(const QString &text, const QString &locale, QNdefNfcTextRecord::Encoding encoding) |
| { |
| QNdefNfcTextRecord rec; |
| rec.setText(text); |
| rec.setLocale(locale); |
| rec.setEncoding(encoding); |
| |
| return addTitle(rec); |
| } |
| |
| /*! |
| Attempts to remove the title record \a text from the smart poster. Removes the record and returns true |
| if the smart poster contains a matching record, otherwise false. |
| */ |
| bool QNdefNfcSmartPosterRecord::removeTitle(const QNdefNfcTextRecord &text) |
| { |
| bool status = false; |
| |
| for (int i = 0; i < d->m_titleList.length(); ++i) { |
| const QNdefNfcTextRecord &rec = d->m_titleList[i]; |
| |
| if (rec.text() == text.text() && rec.locale() == text.locale() && rec.encoding() == text.encoding()) { |
| d->m_titleList.removeAt(i); |
| status = true; |
| break; |
| } |
| } |
| |
| // Convert to payload |
| convertToPayload(); |
| |
| return status; |
| } |
| |
| /*! |
| Attempts to remove a title record with locale \a locale from the smart poster. Removes the record and returns true |
| if the smart poster contains a matching record, otherwise false. |
| */ |
| bool QNdefNfcSmartPosterRecord::removeTitle(const QString &locale) |
| { |
| bool status = false; |
| |
| for (int i = 0; i < d->m_titleList.length(); ++i) { |
| const QNdefNfcTextRecord &rec = d->m_titleList[i]; |
| |
| if (rec.locale() == locale) { |
| d->m_titleList.removeAt(i); |
| status = true; |
| break; |
| } |
| } |
| |
| // Convert to payload |
| convertToPayload(); |
| |
| return status; |
| } |
| |
| /*! |
| Adds the title record list \a titles to the smart poster. Any existing records are overwritten. |
| */ |
| void QNdefNfcSmartPosterRecord::setTitles(const QList<QNdefNfcTextRecord> &titles) |
| { |
| d->m_titleList.clear(); |
| |
| for (int i = 0; i < titles.length(); ++i) { |
| d->m_titleList.append(titles[i]); |
| } |
| |
| // Convert to payload |
| convertToPayload(); |
| } |
| |
| /*! |
| Returns the URI from the smart poster's URI record if set. Otherwise an empty URI is returned. |
| */ |
| QUrl QNdefNfcSmartPosterRecord::uri() const |
| { |
| if (d->m_uri) |
| return d->m_uri->uri(); |
| |
| return QUrl(); |
| } |
| |
| /*! |
| Returns the smart poster's URI record if set. Otherwise an empty URI is returned. |
| */ |
| QNdefNfcUriRecord QNdefNfcSmartPosterRecord::uriRecord() const |
| { |
| if (d->m_uri) |
| return *(d->m_uri); |
| |
| return QNdefNfcUriRecord(); |
| } |
| |
| /*! |
| Sets the URI record to \a url |
| */ |
| void QNdefNfcSmartPosterRecord::setUri(const QNdefNfcUriRecord &url) |
| { |
| if (d->m_uri) |
| delete d->m_uri; |
| |
| d->m_uri = new QNdefNfcUriRecord(url); |
| |
| // Convert to payload |
| convertToPayload(); |
| } |
| |
| /*! |
| Constructs a URI record and sets its content inside the smart poster to \a url |
| */ |
| void QNdefNfcSmartPosterRecord::setUri(const QUrl &url) |
| { |
| QNdefNfcUriRecord rec; |
| rec.setUri(url); |
| |
| setUri(rec); |
| } |
| |
| /*! |
| Returns the action from the action record if available. Otherwise \l UnspecifiedAction is returned. |
| */ |
| QNdefNfcSmartPosterRecord::Action QNdefNfcSmartPosterRecord::action() const |
| { |
| if (d->m_action) |
| return d->m_action->action(); |
| |
| return UnspecifiedAction; |
| } |
| |
| /*! |
| Sets the action record to \a act |
| */ |
| void QNdefNfcSmartPosterRecord::setAction(Action act) |
| { |
| if (!d->m_action) |
| d->m_action = new QNdefNfcActRecord(); |
| |
| d->m_action->setAction(act); |
| |
| // Convert to payload |
| convertToPayload(); |
| } |
| |
| /*! |
| Returns the number of icon records contained inside the smart poster. |
| */ |
| int QNdefNfcSmartPosterRecord::iconCount() const |
| { |
| return d->m_iconList.length(); |
| } |
| |
| /*! |
| Returns the icon record corresponding to the index \a index inside the smart poster, where \a index is a value between 0 and \l iconCount() - 1. Values outside of this range return an empty record. |
| */ |
| QNdefNfcIconRecord QNdefNfcSmartPosterRecord::iconRecord(const int index) const |
| { |
| if (index >= 0 && index < d->m_iconList.length()) |
| return d->m_iconList[index]; |
| |
| return QNdefNfcIconRecord(); |
| } |
| |
| /*! |
| Returns the associated icon record data if the smart poster contains an icon record with MIME type \a mimetype. |
| If \a mimetype is omitted or empty then the first icon's record data is returned. In all other cases, an empty array is returned. |
| */ |
| QByteArray QNdefNfcSmartPosterRecord::icon(const QByteArray& mimetype) const |
| { |
| for (int i = 0; i < d->m_iconList.length(); ++i) { |
| const QNdefNfcIconRecord &icon = d->m_iconList[i]; |
| |
| if (mimetype.isEmpty() || icon.type() == mimetype) |
| return icon.data(); |
| } |
| |
| return QByteArray(); |
| } |
| |
| /*! |
| Returns a copy of all icon records inside the smart poster. |
| */ |
| QList<QNdefNfcIconRecord> QNdefNfcSmartPosterRecord::iconRecords() const |
| { |
| return d->m_iconList; |
| } |
| |
| /*! |
| Adds an icon record \a icon to the smart poster. If the smart poster already contains an icon |
| record with the same type then the existing icon record is replaced. |
| */ |
| void QNdefNfcSmartPosterRecord::addIcon(const QNdefNfcIconRecord &icon) |
| { |
| addIconInternal(icon); |
| |
| // Convert to payload |
| convertToPayload(); |
| } |
| |
| void QNdefNfcSmartPosterRecord::addIconInternal(const QNdefNfcIconRecord &icon) |
| { |
| for (int i = 0; i < d->m_iconList.length(); ++i) { |
| const QNdefNfcIconRecord &rec = d->m_iconList[i]; |
| |
| if (rec.type() == icon.type()) |
| d->m_iconList.removeAt(i); |
| } |
| |
| d->m_iconList.append(icon); |
| } |
| |
| /*! |
| Adds an icon record with type \a type and data \a data to the smart poster. If the smart poster |
| already contains an icon record with the same type then the existing icon record is replaced. |
| */ |
| void QNdefNfcSmartPosterRecord::addIcon(const QByteArray &type, const QByteArray &data) |
| { |
| QNdefNfcIconRecord rec; |
| rec.setType(type); |
| rec.setData(data); |
| |
| addIcon(rec); |
| } |
| |
| /*! |
| Attempts to remove the icon record \a icon from the smart poster. Removes the record and returns true |
| if the smart poster contains a matching record, otherwise false. |
| */ |
| bool QNdefNfcSmartPosterRecord::removeIcon(const QNdefNfcIconRecord &icon) |
| { |
| bool status = false; |
| |
| for (int i = 0; i < d->m_iconList.length(); ++i) { |
| const QNdefNfcIconRecord &rec = d->m_iconList[i]; |
| |
| if (rec.type() == icon.type() && rec.data() == icon.data()) { |
| d->m_iconList.removeAt(i); |
| status = true; |
| break; |
| } |
| } |
| |
| // Convert to payload |
| convertToPayload(); |
| |
| return status; |
| } |
| |
| /*! |
| Attempts to remove the icon record with type \a type from the smart poster. Removes the record |
| and returns true if the smart poster contains a matching record, otherwise false. |
| */ |
| bool QNdefNfcSmartPosterRecord::removeIcon(const QByteArray &type) |
| { |
| bool status = false; |
| |
| for (int i = 0; i < d->m_iconList.length(); ++i) { |
| const QNdefNfcIconRecord &rec = d->m_iconList[i]; |
| |
| if (rec.type() == type) { |
| d->m_iconList.removeAt(i); |
| status = true; |
| break; |
| } |
| } |
| |
| // Convert to payload |
| convertToPayload(); |
| |
| return status; |
| } |
| |
| /*! |
| Adds the icon record list \a icons to the smart poster. |
| Any existing records are overwritten. |
| |
| \sa hasIcon(), icon() |
| */ |
| void QNdefNfcSmartPosterRecord::setIcons(const QList<QNdefNfcIconRecord> &icons) |
| { |
| d->m_iconList.clear(); |
| |
| for (int i = 0; i < icons.length(); ++i) { |
| d->m_iconList.append(icons[i]); |
| } |
| |
| // Convert to payload |
| convertToPayload(); |
| } |
| |
| /*! |
| Returns the size from the size record if available; otherwise returns 0. |
| |
| The value is optional and contains the size in bytes of the object |
| that the URI refers to. It may be used by the device to determine |
| whether it can accommodate the object. |
| |
| \sa setSize() |
| */ |
| quint32 QNdefNfcSmartPosterRecord::size() const |
| { |
| if (d->m_size) |
| return d->m_size->size(); |
| |
| return 0; |
| } |
| |
| /*! |
| Sets the record \a size. The value contains the size in bytes of |
| the object that the URI refers to. |
| |
| \sa size(), hasSize() |
| */ |
| void QNdefNfcSmartPosterRecord::setSize(quint32 size) |
| { |
| if (!d->m_size) |
| d->m_size = new QNdefNfcSizeRecord(); |
| |
| d->m_size->setSize(size); |
| |
| // Convert to payload |
| convertToPayload(); |
| } |
| |
| /*! |
| Returns the UTF-8 encoded MIME type that describes the type of the objects |
| that can be reached via uri(). |
| |
| If the type is not known the return QByteArray is empty. |
| |
| \sa setTypeInfo(), hasTypeInfo() |
| */ |
| QByteArray QNdefNfcSmartPosterRecord::typeInfo() const |
| { |
| if (d->m_type) |
| return d->m_type->typeInfo(); |
| |
| return QByteArray(); |
| } |
| |
| /*! |
| Sets the type record to \a type. \a type must be UTF-8 encoded |
| and describes the type of the object referenced by uri() |
| |
| \sa typeInfo() |
| */ |
| void QNdefNfcSmartPosterRecord::setTypeInfo(const QByteArray &type) |
| { |
| if (d->m_type) |
| delete d->m_type; |
| |
| d->m_type = new QNdefNfcTypeRecord(); |
| d->m_type->setTypeInfo(type); |
| |
| // Convert to payload |
| convertToPayload(); |
| } |
| |
| void QNdefNfcActRecord::setAction(QNdefNfcSmartPosterRecord::Action action) |
| { |
| QByteArray data; |
| data[0] = action; |
| |
| setPayload(data); |
| } |
| |
| QNdefNfcSmartPosterRecord::Action QNdefNfcActRecord::action() const |
| { |
| const QByteArray p = payload(); |
| QNdefNfcSmartPosterRecord::Action value = |
| QNdefNfcSmartPosterRecord::UnspecifiedAction; |
| |
| if (!p.isEmpty()) |
| value = QNdefNfcSmartPosterRecord::Action(static_cast<signed char>(p[0])); |
| |
| return value; |
| } |
| |
| void QNdefNfcIconRecord::setData(const QByteArray &data) |
| { |
| setPayload(data); |
| } |
| |
| QByteArray QNdefNfcIconRecord::data() const |
| { |
| return payload(); |
| } |
| |
| void QNdefNfcSizeRecord::setSize(quint32 size) |
| { |
| QByteArray data; |
| |
| data[0] = (int) ((size & 0xFF000000) >> 24); |
| data[1] = (int) ((size & 0x00FF0000) >> 16); |
| data[2] = (int) ((size & 0x0000FF00) >> 8); |
| data[3] = (int) ((size & 0x000000FF)); |
| |
| setPayload(data); |
| } |
| |
| quint32 QNdefNfcSizeRecord::size() const |
| { |
| const QByteArray p = payload(); |
| |
| if (p.isEmpty()) |
| return 0; |
| |
| return ((p[0] << 24) & 0xFF000000) + ((p[1] << 16) & 0x00FF0000) |
| + ((p[2] << 8) & 0x0000FF00) + (p[3] & 0x000000FF); |
| } |
| |
| void QNdefNfcTypeRecord::setTypeInfo(const QByteArray &type) |
| { |
| setPayload(type); |
| } |
| |
| QByteArray QNdefNfcTypeRecord::typeInfo() const |
| { |
| return payload(); |
| } |
| |
| QT_END_NAMESPACE |