Qt 5.11 | Qt NFC | NDEF Editor Example | mainwindow.cpp Example File

Qt 5.11.3 Reference Documentation

# mainwindow.cpp Example File

ndefeditor/mainwindow.cpp

      /****************************************************************************
      **
      ** Copyright (C) 2017 The Qt Company Ltd.
      ** Contact: https://www.qt.io/licensing/
      **
      ** This file is part of the QtNfc module of the Qt Toolkit.
      **
      ** $QT_BEGIN_LICENSE:BSD$
      ** 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.
      **
      ** BSD License Usage
      ** Alternatively, 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 <QtNfc/qndefnfcurirecord.h>
      #include <QtNfc/qndefnfctextrecord.h>
      #include <QtNfc/qndefrecord.h>
      #include <QtNfc/qndefmessage.h>
      #include <QtNfc/qnearfieldmanager.h>
      #include <QtNfc/qnearfieldtarget.h>

      #include <QtWidgets/QMenu>
      #include <QtWidgets/QVBoxLayout>
      #include <QtWidgets/QFrame>
      #include <QtWidgets/QLabel>
      #include <QtWidgets/QFileDialog>

      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, &QNearFieldManager::targetDetected,
                  this, &MainWindow::targetDetected);
          connect(m_manager, &QNearFieldManager::targetLost,
                  this, &MainWindow::targetLost);
      }

      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, &QNearFieldTarget::ndefMessageRead, this, &MainWindow::ndefMessageRead);
              connect(target, &QNearFieldTarget::error, this, &MainWindow::targetError);

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

              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"