- Qt 5.5
- Qt NFC
- NDEF Editor Example
- mainwindow.cpp Example File
- Qt 5.5.1 Reference Documentation

# mainwindow.cpp Example File

ndefeditor/mainwindow.cpp

    /****************************************************************************
    **
    ** Copyright (C) 2015 The Qt Company Ltd.
    ** Contact: http://www.qt.io/licensing/
    **
    ** This file is part of the QtNfc module of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:BSD$
    ** You may use this file under the terms of the BSD license as follows:
    **
    ** "Redistribution and use in source and binary forms, with or without
    ** modification, are permitted provided that the following conditions are
    ** met:
    **   * Redistributions of source code must retain the above copyright
    **     notice, this list of conditions and the following disclaimer.
    **   * Redistributions in binary form must reproduce the above copyright
    **     notice, this list of conditions and the following disclaimer in
    **     the documentation and/or other materials provided with the
    **     distribution.
    **   * Neither the name of The Qt Company Ltd nor the names of its
    **     contributors may be used to endorse or promote products derived
    **     from this software without specific prior written permission.
    **
    **
    ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/

    #include "mainwindow.h"
    #include "ui_mainwindow.h"

    #include "textrecordeditor.h"
    #include "urirecordeditor.h"
    #include "mimeimagerecordeditor.h"

    #include <QtCore/QTime>
    #include <QMenu>
    #include <QVBoxLayout>
    #include <QFrame>
    #include <QLabel>
    #include <QFileDialog>

    #include <qnearfieldmanager.h>
    #include <qnearfieldtarget.h>
    #include <qndefrecord.h>
    #include <qndefnfctextrecord.h>
    #include <qndefnfcurirecord.h>
    #include <qndefmessage.h>

    #include <QtCore/QDebug>

    class EmptyRecordLabel : public QLabel
    {
        Q_OBJECT

    public:
        EmptyRecordLabel() : QLabel(tr("Empty Record")) { }
        ~EmptyRecordLabel() { }

        void setRecord(const QNdefRecord &record)
        {
            Q_UNUSED(record);
        }

        QNdefRecord record() const
        {
            return QNdefRecord();
        }
    };

    class UnknownRecordLabel : public QLabel
    {
        Q_OBJECT

    public:
        UnknownRecordLabel() : QLabel(tr("Unknown Record Type")) { }
        ~UnknownRecordLabel() { }

        void setRecord(const QNdefRecord &record) { m_record = record; }
        QNdefRecord record() const { return m_record; }

    private:
        QNdefRecord m_record;
    };

    template <typename T>
    void addRecord(Ui::MainWindow *ui, const QNdefRecord &record = QNdefRecord())
    {
        QVBoxLayout *vbox = qobject_cast<QVBoxLayout *>(ui->scrollAreaWidgetContents->layout());
        if (!vbox)
            return;

        if (!vbox->isEmpty()) {
            QFrame *hline = new QFrame;
            hline->setFrameShape(QFrame::HLine);
            hline->setObjectName(QStringLiteral("line-spacer"));

            vbox->addWidget(hline);
        }

        T *recordEditor = new T;
        recordEditor->setObjectName(QStringLiteral("record-editor"));

        if (!record.isEmpty())
            recordEditor->setRecord(record);

        vbox->addWidget(recordEditor);
    }

    MainWindow::MainWindow(QWidget *parent)
    :   QMainWindow(parent), ui(new Ui::MainWindow), m_touchAction(NoAction)
    {
        ui->setupUi(this);

        QMenu *addRecordMenu = new QMenu(this);
        addRecordMenu->addAction(tr("NFC Text Record"), this, SLOT(addNfcTextRecord()));
        addRecordMenu->addAction(tr("NFC URI Record"), this, SLOT(addNfcUriRecord()));
        addRecordMenu->addAction(tr("MIME Image Record"), this, SLOT(addMimeImageRecord()));
        addRecordMenu->addAction(tr("Empty Record"), this, SLOT(addEmptyRecord()));
        ui->addRecord->setMenu(addRecordMenu);

        QVBoxLayout *vbox = new QVBoxLayout;
        ui->scrollAreaWidgetContents->setLayout(vbox);

        m_manager = new QNearFieldManager(this);
        connect(m_manager, SIGNAL(targetDetected(QNearFieldTarget*)),
                this, SLOT(targetDetected(QNearFieldTarget*)));
        connect(m_manager, SIGNAL(targetLost(QNearFieldTarget*)),
                this, SLOT(targetLost(QNearFieldTarget*)));
    }

    MainWindow::~MainWindow()
    {
        delete ui;
    }

    void MainWindow::addNfcTextRecord()
    {
        addRecord<TextRecordEditor>(ui);
    }

    void MainWindow::addNfcUriRecord()
    {
        addRecord<UriRecordEditor>(ui);
    }

    void MainWindow::addMimeImageRecord()
    {
        addRecord<MimeImageRecordEditor>(ui);
    }

    void MainWindow::addEmptyRecord()
    {
        addRecord<EmptyRecordLabel>(ui);
    }

    void MainWindow::loadMessage()
    {
        QString filename = QFileDialog::getOpenFileName(this, tr("Select NDEF Message"));
        if (filename.isEmpty())
            return;

        QFile file(filename);
        if (!file.open(QIODevice::ReadOnly))
            return;

        QByteArray ndef = file.readAll();

        ndefMessageRead(QNdefMessage::fromByteArray(ndef));

        file.close();
    }

    void MainWindow::saveMessage()
    {
        QString filename = QFileDialog::getSaveFileName(this, tr("Select NDEF Message"));
        if (filename.isEmpty())
            return;

        QFile file(filename);
        if (!file.open(QIODevice::WriteOnly))
            return;

        file.write(ndefMessage().toByteArray());

        file.close();
    }

    void MainWindow::touchReceive()
    {
        ui->status->setStyleSheet(QStringLiteral("background: blue"));

        m_touchAction = ReadNdef;

        m_manager->setTargetAccessModes(QNearFieldManager::NdefReadTargetAccess);
        m_manager->startTargetDetection();
    }

    void MainWindow::touchStore()
    {
        ui->status->setStyleSheet(QStringLiteral("background: yellow"));

        m_touchAction = WriteNdef;

        m_manager->setTargetAccessModes(QNearFieldManager::NdefWriteTargetAccess);
        m_manager->startTargetDetection();
    }

    void MainWindow::targetDetected(QNearFieldTarget *target)
    {
        switch (m_touchAction) {
        case NoAction:
            break;
        case ReadNdef:
            connect(target, SIGNAL(ndefMessageRead(QNdefMessage)),
                    this, SLOT(ndefMessageRead(QNdefMessage)));
            connect(target, SIGNAL(error(QNearFieldTarget::Error,QNearFieldTarget::RequestId)),
                    this, SLOT(targetError(QNearFieldTarget::Error,QNearFieldTarget::RequestId)));

            m_request = target->readNdefMessages();
            if (!m_request.isValid()) // cannot read messages
                targetError(QNearFieldTarget::NdefReadError, m_request);
            break;
        case WriteNdef:
            connect(target, SIGNAL(ndefMessagesWritten()), this, SLOT(ndefMessageWritten()));
            connect(target, SIGNAL(error(QNearFieldTarget::Error,QNearFieldTarget::RequestId)),
                    this, SLOT(targetError(QNearFieldTarget::Error,QNearFieldTarget::RequestId)));

            m_request = target->writeNdefMessages(QList<QNdefMessage>() << ndefMessage());
            if (!m_request.isValid()) // cannot write messages
                targetError(QNearFieldTarget::NdefWriteError, m_request);
            break;
        }
    }

    void MainWindow::targetLost(QNearFieldTarget *target)
    {
        target->deleteLater();
    }

    void MainWindow::ndefMessageRead(const QNdefMessage &message)
    {
        clearMessage();

        foreach (const QNdefRecord &record, message) {
            if (record.isRecordType<QNdefNfcTextRecord>()) {
                addRecord<TextRecordEditor>(ui, record);
            } else if (record.isRecordType<QNdefNfcUriRecord>()) {
                addRecord<UriRecordEditor>(ui, record);
            } else if (record.typeNameFormat() == QNdefRecord::Mime &&
                       record.type().startsWith("image/")) {
                addRecord<MimeImageRecordEditor>(ui, record);
            } else if (record.isEmpty()) {
                addRecord<EmptyRecordLabel>(ui);
            } else {
                addRecord<UnknownRecordLabel>(ui, record);
            }
        }

        ui->status->setStyleSheet(QString());
        m_manager->setTargetAccessModes(QNearFieldManager::NoTargetAccess);
        m_manager->stopTargetDetection();
        m_request = QNearFieldTarget::RequestId();
        ui->statusBar->clearMessage();
    }

    void MainWindow::ndefMessageWritten()
    {
        ui->status->setStyleSheet(QString());
        m_manager->setTargetAccessModes(QNearFieldManager::NoTargetAccess);
        m_manager->stopTargetDetection();
        m_request = QNearFieldTarget::RequestId();
        ui->statusBar->clearMessage();
    }

    void MainWindow::targetError(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id)
    {
        Q_UNUSED(error);
        Q_UNUSED(id);

        if (m_request == id) {
            switch (error) {
            case QNearFieldTarget::NoError:
                ui->statusBar->clearMessage();
                break;
            case QNearFieldTarget::UnsupportedError:
                ui->statusBar->showMessage(tr("Unsupported tag"));
                break;
            case QNearFieldTarget::TargetOutOfRangeError:
                ui->statusBar->showMessage(tr("Tag removed from field"));
                break;
            case QNearFieldTarget::NoResponseError:
                ui->statusBar->showMessage(tr("No response from tag"));
                break;
            case QNearFieldTarget::ChecksumMismatchError:
                ui->statusBar->showMessage(tr("Checksum mismatch"));
                break;
            case QNearFieldTarget::InvalidParametersError:
                ui->statusBar->showMessage(tr("Invalid parameters"));
                break;
            case QNearFieldTarget::NdefReadError:
                ui->statusBar->showMessage(tr("NDEF read error"));
                break;
            case QNearFieldTarget::NdefWriteError:
                ui->statusBar->showMessage(tr("NDEF write error"));
                break;
            default:
                ui->statusBar->showMessage(tr("Unknown error"));
            }

            ui->status->setStyleSheet(QString());
            m_manager->setTargetAccessModes(QNearFieldManager::NoTargetAccess);
            m_manager->stopTargetDetection();
            m_request = QNearFieldTarget::RequestId();
        }
    }

    void MainWindow::clearMessage()
    {
        QWidget *scrollArea = ui->scrollAreaWidgetContents;

        qDeleteAll(scrollArea->findChildren<QWidget *>(QStringLiteral("line-spacer")));
        qDeleteAll(scrollArea->findChildren<QWidget *>(QStringLiteral("record-editor")));
    }

    QNdefMessage MainWindow::ndefMessage() const
    {
        QVBoxLayout *vbox = qobject_cast<QVBoxLayout *>(ui->scrollAreaWidgetContents->layout());
        if (!vbox)
            return QNdefMessage();

        QNdefMessage message;

        for (int i = 0; i < vbox->count(); ++i) {
            QWidget *widget = vbox->itemAt(i)->widget();

            if (TextRecordEditor *editor = qobject_cast<TextRecordEditor *>(widget)) {
                message.append(editor->record());
            } else if (UriRecordEditor *editor = qobject_cast<UriRecordEditor *>(widget)) {
                message.append(editor->record());
            } else if (MimeImageRecordEditor *editor = qobject_cast<MimeImageRecordEditor *>(widget)) {
                message.append(editor->record());
            } else if (qobject_cast<EmptyRecordLabel *>(widget)) {
                message.append(QNdefRecord());
            } else if (UnknownRecordLabel *label = qobject_cast<UnknownRecordLabel *>(widget)) {
                message.append(label->record());
            }
        }

        return message;
    }

    #include "mainwindow.moc"