// Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include "annotatedurl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include AnnotatedUrl::AnnotatedUrl(QObject *parent) : QObject(parent), manager(new QNearFieldManager(this)) { connect(manager, &QNearFieldManager::targetDetected, this, &AnnotatedUrl::targetDetected); connect(manager, &QNearFieldManager::targetLost, this, &AnnotatedUrl::targetLost); connect(manager, &QNearFieldManager::adapterStateChanged, this, &AnnotatedUrl::handleAdapterStateChange); //! [populateFilter] messageFilter.setOrderMatch(false); messageFilter.appendRecord(1, 100); messageFilter.appendRecord(1, 1); messageFilter.appendRecord(QNdefRecord::Mime, "", 0, 1); //! [populateFilter] } AnnotatedUrl::~AnnotatedUrl() { } void AnnotatedUrl::startDetection() { if (!manager->isEnabled()) { qWarning() << "NFC not enabled"; emit nfcStateChanged(false); return; } if (manager->startTargetDetection(QNearFieldTarget::NdefAccess)) emit nfcStateChanged(true); } void AnnotatedUrl::targetDetected(QNearFieldTarget *target) { if (!target) return; connect(target, &QNearFieldTarget::ndefMessageRead, this, &AnnotatedUrl::handlePolledNdefMessage); connect(target, &QNearFieldTarget::error, this, [this]() { emit tagError("Tag read error"); }); target->readNdefMessages(); } void AnnotatedUrl::targetLost(QNearFieldTarget *target) { if (target) target->deleteLater(); } void AnnotatedUrl::handlePolledNdefMessage(QNdefMessage message) { QNearFieldTarget *target = qobject_cast(sender()); handleMessage(message, target); } //! [handleAdapterState] void AnnotatedUrl::handleAdapterStateChange(QNearFieldManager::AdapterState state) { if (state == QNearFieldManager::AdapterState::Online) { startDetection(); } else if (state == QNearFieldManager::AdapterState::Offline) { manager->stopTargetDetection(); emit nfcStateChanged(false); } } //! [handleAdapterState] //! [handleMessage 1] void AnnotatedUrl::handleMessage(const QNdefMessage &message, QNearFieldTarget *target) { //! [handleMessage 1] Q_UNUSED(target); //! [handleMessage 2] if (!messageFilter.match(message)) { emit tagError("Invalid message format"); return; } //! [handleMessage 2] enum { MatchedNone, MatchedFirst, MatchedEnglish, MatchedLanguage, MatchedLanguageAndCountry } bestMatch = MatchedNone; QLocale defaultLocale; QString title; QUrl url; QPixmap pixmap; //! [handleMessage 3] for (const QNdefRecord &record : message) { if (record.isRecordType()) { QNdefNfcTextRecord textRecord(record); title = textRecord.text(); QLocale locale(textRecord.locale()); //! [handleMessage 3] // already found best match if (bestMatch == MatchedLanguageAndCountry) { // do nothing } else if (bestMatch <= MatchedLanguage && locale == defaultLocale) { bestMatch = MatchedLanguageAndCountry; } else if (bestMatch <= MatchedEnglish && locale.language() == defaultLocale.language()) { bestMatch = MatchedLanguage; } else if (bestMatch <= MatchedFirst && locale.language() == QLocale::English) { bestMatch = MatchedEnglish; } else if (bestMatch == MatchedNone) { bestMatch = MatchedFirst; } //! [handleMessage 4] } else if (record.isRecordType()) { QNdefNfcUriRecord uriRecord(record); url = uriRecord.uri(); } else if (record.typeNameFormat() == QNdefRecord::Mime && record.type().startsWith("image/")) { pixmap = QPixmap::fromImage(QImage::fromData(record.payload())); } //! [handleMessage 4] //! [handleMessage 5] } emit annotatedUrl(url, title, pixmap); } //! [handleMessage 5]