summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIevgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io>2022-11-09 15:56:22 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-02-08 15:44:45 +0000
commitb9ab0e98aaae740c8a97273742f56768ceb6ff76 (patch)
treecd8eb0fceb777f6bbc43b5403baaca3a6095bde2
parent809f007d111b41263ff80ca8dcd157048cb88d03 (diff)
downloadqtconnectivity-b9ab0e98aaae740c8a97273742f56768ceb6ff76.tar.gz
QtNfc: Rewrite NDEF Editor example using Qt Quick Components
This makes the example look more native on mobile platforms. Leave only the functionality related to reading and writing of text and URI NDEF records to simplify the code. Removed functionality includes saving/reading messages to files, and support for image NDEF records. Fixes: QTBUG-103949 Change-Id: Ie14e3009e2d0238b266eb9690795ca6b56c0010c Reviewed-by: Mitch Curtis <mitch.curtis@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> (cherry picked from commit 115b4d947adf90a706f76de831f34960e3c62a9c) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--CMakeLists.txt3
-rw-r--r--LICENSES/Apache-2.0.txt61
-rw-r--r--examples/nfc/CMakeLists.txt2
-rw-r--r--examples/nfc/ndefeditor/CMakeLists.txt58
-rw-r--r--examples/nfc/ndefeditor/Info.cmake.plist54
-rw-r--r--examples/nfc/ndefeditor/Info.plist41
-rw-r--r--examples/nfc/ndefeditor/Info.qmake.plist49
-rw-r--r--examples/nfc/ndefeditor/Main.qml9
-rw-r--r--examples/nfc/ndefeditor/MainWindow.qml385
-rw-r--r--examples/nfc/ndefeditor/NdefRecordDelegate.qml50
-rw-r--r--examples/nfc/ndefeditor/android/AndroidManifest.xml48
-rw-r--r--examples/nfc/ndefeditor/doc/images/ndefeditor.pngbin13866 -> 29285 bytes
-rw-r--r--examples/nfc/ndefeditor/doc/src/ndefeditor.qdoc71
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20/add.pngbin0 -> 99 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20/arrow_back.pngbin0 -> 115 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20/file_download.pngbin0 -> 140 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20/file_upload.pngbin0 -> 141 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20/link.pngbin0 -> 168 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20/text_snippet.pngbin0 -> 197 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/add.pngbin0 -> 133 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/arrow_back.pngbin0 -> 157 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/file_download.pngbin0 -> 198 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/file_upload.pngbin0 -> 197 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/link.pngbin0 -> 273 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/text_snippet.pngbin0 -> 249 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/add.pngbin0 -> 148 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/arrow_back.pngbin0 -> 174 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/file_download.pngbin0 -> 268 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/file_upload.pngbin0 -> 266 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/link.pngbin0 -> 336 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/text_snippet.pngbin0 -> 295 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/add.pngbin0 -> 167 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/arrow_back.pngbin0 -> 234 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/file_download.pngbin0 -> 311 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/file_upload.pngbin0 -> 304 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/link.pngbin0 -> 457 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/text_snippet.pngbin0 -> 377 bytes
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/index.theme22
-rw-r--r--examples/nfc/ndefeditor/icons/ndefeditor/qt_attribution.json11
-rw-r--r--examples/nfc/ndefeditor/main.cpp21
-rw-r--r--examples/nfc/ndefeditor/mainwindow.cpp376
-rw-r--r--examples/nfc/ndefeditor/mainwindow.h79
-rw-r--r--examples/nfc/ndefeditor/mainwindow.ui225
-rw-r--r--examples/nfc/ndefeditor/mimeimagerecordeditor.cpp170
-rw-r--r--examples/nfc/ndefeditor/mimeimagerecordeditor.h50
-rw-r--r--examples/nfc/ndefeditor/mimeimagerecordeditor.ui86
-rw-r--r--examples/nfc/ndefeditor/ndefeditor.pro72
-rw-r--r--examples/nfc/ndefeditor/ndefmessagemodel.cpp156
-rw-r--r--examples/nfc/ndefeditor/ndefmessagemodel.h53
-rw-r--r--examples/nfc/ndefeditor/nfcmanager.cpp29
-rw-r--r--examples/nfc/ndefeditor/nfcmanager.h33
-rw-r--r--examples/nfc/ndefeditor/nfctarget.cpp31
-rw-r--r--examples/nfc/ndefeditor/nfctarget.h34
-rw-r--r--examples/nfc/ndefeditor/qmldir5
-rw-r--r--examples/nfc/ndefeditor/textrecordeditor.cpp44
-rw-r--r--examples/nfc/ndefeditor/textrecordeditor.h34
-rw-r--r--examples/nfc/ndefeditor/textrecordeditor.ui101
-rw-r--r--examples/nfc/ndefeditor/urirecordeditor.cpp33
-rw-r--r--examples/nfc/ndefeditor/urirecordeditor.h33
-rw-r--r--examples/nfc/ndefeditor/urirecordeditor.ui45
-rw-r--r--examples/nfc/nfc.pro7
61 files changed, 1090 insertions, 1491 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cba619fb..f5db4b62 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,7 +13,8 @@ project(QtConnectivity
set(QT_REPO_NOT_WARNINGS_CLEAN TRUE)
find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals Core Network)
-find_package(Qt6 ${PROJECT_VERSION} CONFIG OPTIONAL_COMPONENTS DBus Gui Widgets Quick)
+find_package(Qt6 ${PROJECT_VERSION} CONFIG OPTIONAL_COMPONENTS
+ DBus Gui Widgets Quick QuickControls2)
if(NOT TARGET Qt::Network)
message(NOTICE "Skipping the build as the condition \"TARGET Qt::Network\" is not met.")
diff --git a/LICENSES/Apache-2.0.txt b/LICENSES/Apache-2.0.txt
new file mode 100644
index 00000000..136d9004
--- /dev/null
+++ b/LICENSES/Apache-2.0.txt
@@ -0,0 +1,61 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+ 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+ 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+ 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+ (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
+ (b) You must cause any modified files to carry prominent notices stating that You changed the files; and
+ (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+ (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+ 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+ 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+ 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+ 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/examples/nfc/CMakeLists.txt b/examples/nfc/CMakeLists.txt
index 68488355..47bc9416 100644
--- a/examples/nfc/CMakeLists.txt
+++ b/examples/nfc/CMakeLists.txt
@@ -3,5 +3,7 @@
if(TARGET Qt::Widgets)
qt_internal_add_example(annotatedurl)
+endif()
+if(TARGET Qt::QuickControls2)
qt_internal_add_example(ndefeditor)
endif()
diff --git a/examples/nfc/ndefeditor/CMakeLists.txt b/examples/nfc/ndefeditor/CMakeLists.txt
index 2d7bb60b..a3b2c80c 100644
--- a/examples/nfc/ndefeditor/CMakeLists.txt
+++ b/examples/nfc/ndefeditor/CMakeLists.txt
@@ -1,11 +1,10 @@
-# Copyright (C) 2022 The Qt Company Ltd.
+# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(ndefeditor LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
-set(CMAKE_AUTOUIC ON)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
@@ -13,44 +12,55 @@ endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/nfc/ndefeditor")
-find_package(Qt6 REQUIRED COMPONENTS Core Gui Nfc Widgets)
+find_package(Qt6 REQUIRED COMPONENTS Core Nfc Quick QuickControls2)
qt_add_executable(ndefeditor
- MANUAL_FINALIZATION
main.cpp
- mainwindow.cpp mainwindow.h mainwindow.ui
- mimeimagerecordeditor.cpp mimeimagerecordeditor.h mimeimagerecordeditor.ui
- textrecordeditor.cpp textrecordeditor.h textrecordeditor.ui
- urirecordeditor.cpp urirecordeditor.h urirecordeditor.ui
+)
+
+set(icon_files)
+foreach(icon IN ITEMS add arrow_back file_download file_upload link text_snippet)
+ foreach(scale IN ITEMS "" "@2" "@3" "@4")
+ list(APPEND icon_files "icons/ndefeditor/20x20${scale}/${icon}.png")
+ endforeach()
+endforeach()
+
+qt_add_resources(ndefeditor "theme" FILES
+ ${icon_files}
+ icons/ndefeditor/index.theme
+)
+
+qt_add_qml_module(ndefeditor
+ URI NdefEditor
+ VERSION 1.0
+ AUTO_RESOURCE_PREFIX
+ QML_FILES
+ Main.qml
+ MainWindow.qml
+ NdefRecordDelegate.qml
+ SOURCES
+ nfcmanager.h nfcmanager.cpp
+ nfctarget.h nfctarget.cpp
+ ndefmessagemodel.h ndefmessagemodel.cpp
)
set_target_properties(ndefeditor PROPERTIES
- WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
+ WIN32_EXECUTABLE TRUE
)
if(IOS)
set_target_properties(ndefeditor PROPERTIES
- MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist"
+ MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.cmake.plist"
)
endif()
-target_link_libraries(ndefeditor PUBLIC
- Qt::Core
- Qt::Gui
- Qt::Nfc
- Qt::Widgets
+target_link_libraries(ndefeditor PRIVATE
+ Qt6::Core
+ Qt6::Nfc
+ Qt6::Quick
)
-if(ANDROID)
- set_property(TARGET ndefeditor
- APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
- ${CMAKE_CURRENT_SOURCE_DIR}/android
- )
-endif()
-
-qt_finalize_target(ndefeditor)
-
install(TARGETS ndefeditor
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
diff --git a/examples/nfc/ndefeditor/Info.cmake.plist b/examples/nfc/ndefeditor/Info.cmake.plist
new file mode 100644
index 00000000..ee87b3b2
--- /dev/null
+++ b/examples/nfc/ndefeditor/Info.cmake.plist
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+
+ <key>CFBundleName</key>
+ <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
+
+ <key>CFBundleDisplayName</key>
+ <string>NDEF Editor</string>
+
+ <key>CFBundleIdentifier</key>
+ <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
+
+ <key>CFBundleExecutable</key>
+ <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+
+ <key>CFBundleVersion</key>
+ <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
+
+ <key>CFBundleShortVersionString</key>
+ <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
+
+ <key>CFBundleIconFile</key>
+ <string>${MACOSX_BUNDLE_ICON_FILE}</string>
+
+ <key>CFBundleDevelopmentRegion</key>
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
+ <key>CFBundleAllowMixedLocalizations</key>
+ <true/>
+
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+
+ <key>NFCReaderUsageDescription</key>
+ <string>Qt's ndefeditor wants to access your NFC hardware</string>
+
+ <key>UILaunchStoryboardName</key>
+ <string>LaunchScreen</string>
+
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+</dict>
+</plist>
diff --git a/examples/nfc/ndefeditor/Info.plist b/examples/nfc/ndefeditor/Info.plist
deleted file mode 100644
index b567f11a..00000000
--- a/examples/nfc/ndefeditor/Info.plist
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>CFBundleDisplayName</key>
- <string>${PRODUCT_NAME}</string>
- <key>CFBundleExecutable</key>
- <string>${EXECUTABLE_NAME}</string>
- <key>CFBundleIconFile</key>
- <string>${ASSETCATALOG_COMPILER_APPICON_NAME}</string>
- <key>CFBundleIdentifier</key>
- <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
- <key>CFBundleName</key>
- <string>${PRODUCT_NAME}</string>
- <key>CFBundlePackageType</key>
- <string>APPL</string>
- <key>CFBundleShortVersionString</key>
- <string>${QMAKE_SHORT_VERSION}</string>
- <key>CFBundleSignature</key>
- <string>${QMAKE_PKGINFO_TYPEINFO}</string>
- <key>CFBundleVersion</key>
- <string>${QMAKE_FULL_VERSION}</string>
- <key>LSRequiresIPhoneOS</key>
- <true/>
- <key>MinimumOSVersion</key>
- <string>${IPHONEOS_DEPLOYMENT_TARGET}</string>
- <key>NFCReaderUsageDescription</key>
- <string>Qt's ndefeditor wants to access your NFC hardware</string>
- <key>UILaunchStoryboardName</key>
- <string>LaunchScreen</string>
- <key>UISupportedInterfaceOrientations</key>
- <array>
- <string>UIInterfaceOrientationPortrait</string>
- <string>UIInterfaceOrientationPortraitUpsideDown</string>
- <string>UIInterfaceOrientationLandscapeLeft</string>
- <string>UIInterfaceOrientationLandscapeRight</string>
- </array>
-</dict>
-</plist>
diff --git a/examples/nfc/ndefeditor/Info.qmake.plist b/examples/nfc/ndefeditor/Info.qmake.plist
new file mode 100644
index 00000000..079533e6
--- /dev/null
+++ b/examples/nfc/ndefeditor/Info.qmake.plist
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+
+ <key>CFBundleDisplayName</key>
+ <string>NDEF Editor</string>
+
+ <key>CFBundleIdentifier</key>
+ <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+
+ <key>CFBundleVersion</key>
+ <string>${QMAKE_FULL_VERSION}</string>
+
+ <key>CFBundleShortVersionString</key>
+ <string>${QMAKE_SHORT_VERSION}</string>
+
+ <key>CFBundleIconFile</key>
+ <string>${ASSETCATALOG_COMPILER_APPICON_NAME}</string>
+
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+
+ <key>NFCReaderUsageDescription</key>
+ <string>Qt's ndefeditor wants to access your NFC hardware</string>
+
+ <key>UILaunchStoryboardName</key>
+ <string>LaunchScreen</string>
+
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+</dict>
+</plist>
diff --git a/examples/nfc/ndefeditor/Main.qml b/examples/nfc/ndefeditor/Main.qml
new file mode 100644
index 00000000..c5435e26
--- /dev/null
+++ b/examples/nfc/ndefeditor/Main.qml
@@ -0,0 +1,9 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+MainWindow {
+ width: 480
+ height: 640
+ visible: true
+ title: qsTr("NDEF Editor")
+}
diff --git a/examples/nfc/ndefeditor/MainWindow.qml b/examples/nfc/ndefeditor/MainWindow.qml
new file mode 100644
index 00000000..0dc5ee46
--- /dev/null
+++ b/examples/nfc/ndefeditor/MainWindow.qml
@@ -0,0 +1,385 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Layouts
+
+import NdefEditor
+
+ApplicationWindow {
+ id: window
+
+ enum TargetDetectedAction {
+ NoAction,
+ ReadMessage,
+ WriteMessage
+ }
+
+ StackView {
+ id: stack
+ initialItem: mainView
+ anchors.fill: parent
+ }
+
+ property int targetDetectedAction: MainWindow.NoAction
+
+ Component {
+ id: mainView
+
+ ColumnLayout {
+ ToolBar {
+ Layout.fillWidth: true
+
+ RowLayout {
+ anchors.fill: parent
+ Label {
+ text: qsTr("NDEF Editor")
+ elide: Label.ElideRight
+ horizontalAlignment: Qt.AlignHCenter
+ verticalAlignment: Qt.AlignVCenter
+ Layout.fillWidth: true
+ }
+ }
+ }
+
+ Pane {
+ id: writeTab
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ Flickable {
+ anchors.fill: parent
+ contentHeight: contentItem.childrenRect.height
+
+ ColumnLayout {
+ width: parent.width
+
+ ItemDelegate {
+ icon.name: "file_download"
+ text: qsTr("Read Tag")
+ Layout.fillWidth: true
+
+ onClicked: window.readTag()
+ }
+
+ ItemDelegate {
+ icon.name: "file_upload"
+ text: qsTr("Write to Tag")
+ Layout.fillWidth: true
+
+ onClicked: window.writeTag()
+ }
+
+ ItemDelegate {
+ icon.name: "add"
+ text: qsTr("Add a Record")
+ Layout.fillWidth: true
+
+ onClicked: addRecordMenu.open()
+
+ Menu {
+ id: addRecordMenu
+ title: qsTr("Add record")
+
+ MenuItem {
+ icon.name: "text_snippet"
+ text: qsTr("Text record")
+ onTriggered: stack.push(textRecordDialog)
+ }
+ MenuItem {
+ icon.name: "link"
+ text: qsTr("URI record")
+ onTriggered: stack.push(uriRecordDialog)
+ }
+ }
+ }
+
+ Item {
+ implicitHeight: 20
+ }
+
+ Label {
+ text: qsTr(
+ "Use buttons above to read an NFC tag or add records manually.\n\n"
+ + "Once added, swipe to the right to access options for each record.")
+ wrapMode: Text.Wrap
+ visible: messages.count === 0
+ Layout.fillWidth: true
+ }
+
+ Repeater {
+ id: messages
+ model: messageModel
+
+ delegate: NdefRecordDelegate {
+ Layout.fillWidth: true
+
+ onDeleteClicked: messageModel.removeRow(index)
+
+ onClicked: {
+ if (recordType === NdefMessageModel.TextRecord) {
+ stack.push(textRecordDialog, {
+ text: recordText,
+ modelIndex: index
+ })
+ } else if (recordType === NdefMessageModel.UriRecord) {
+ stack.push(uriRecordDialog, {
+ uri: recordText,
+ modelIndex: index
+ })
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ NdefMessageModel {
+ id: messageModel
+ }
+
+ NfcManager {
+ id: nfcManager
+ onTargetDetected: (target) => { window.handleTargetDetected(target) }
+ }
+
+ Connections {
+ id: targetConnections
+ target: null
+
+ function onNdefMessageRead(message) {
+ messageModel.message = message
+ }
+
+ function onRequestCompleted() {
+ communicationOverlay.close()
+ window.targetDetectedAction = MainWindow.NoAction
+ releaseTarget()
+ }
+
+ function onError(code) {
+ communicationOverlay.close()
+ errorNotification.errorMessage = window.describeError(code)
+ errorNotification.open()
+ window.targetDetectedAction = MainWindow.NoAction
+ releaseTarget()
+ }
+
+ function releaseTarget() {
+ target?.destroy()
+ }
+ }
+
+ function handleTargetDetected(target: NfcTarget) {
+ targetConnections.releaseTarget()
+
+ let ok = true
+
+ if (targetDetectedAction === MainWindow.ReadMessage) {
+ targetConnections.target = target
+ communicationOverlay.message = qsTr("Target detected. Reading messages...")
+ errorNotification.errorMessage = qsTr("NDEF read error")
+ ok = target.readNdefMessages()
+ } else if (targetDetectedAction === MainWindow.WriteMessage) {
+ targetConnections.target = target
+ communicationOverlay.message = qsTr("Target detected. Writing the message...")
+ errorNotification.errorMessage = qsTr("NDEF write error")
+ ok = target.writeNdefMessage(messageModel.message)
+ } else {
+ target.destroy()
+ return
+ }
+
+ if (!ok) {
+ communicationOverlay.close()
+ errorNotification.open()
+ targetConnections.releaseTarget()
+ }
+ }
+
+ function readTag() {
+ messageModel.clearMessage()
+ window.targetDetectedAction = MainWindow.ReadMessage
+ nfcManager.startTargetDetection()
+ communicationOverlay.title = qsTr("Read Tag")
+ communicationOverlay.message = qsTr("Approach an NFC tag.")
+ communicationOverlay.open()
+ }
+
+ function writeTag() {
+ window.targetDetectedAction = MainWindow.WriteMessage
+ nfcManager.startTargetDetection()
+ communicationOverlay.title = qsTr("Write to Tag")
+ communicationOverlay.message = qsTr("Approach an NFC tag.")
+ communicationOverlay.open()
+ }
+
+ function describeError(error) {
+ switch (error) {
+ case 2: return qsTr("Usupported feature")
+ case 3: return qsTr("Target out of range")
+ case 4: return qsTr("No response")
+ case 5: return qsTr("Checksum mismatch")
+ case 6: return qsTr("Invalid parameters")
+ case 7: return qsTr("Connection error")
+ case 8: return qsTr("NDEF read error")
+ case 9: return qsTr("NDEF write error")
+ case 10: return qsTr("Command error")
+ case 11: return qsTr("Timeout")
+ }
+
+ return qsTr("Unknown error")
+ }
+
+ Dialog {
+ id: communicationOverlay
+
+ property alias message: messageLabel.text
+
+ anchors.centerIn: Overlay.overlay
+
+ modal: true
+ standardButtons: Dialog.Cancel
+
+ ColumnLayout {
+ Label {
+ id: messageLabel
+ }
+
+ BusyIndicator {
+ Layout.fillWidth: true
+ }
+ }
+
+ onClosed: nfcManager.stopTargetDetection()
+ }
+
+ MessageDialog {
+ property alias errorMessage: errorNotification.text
+
+ id: errorNotification
+
+ buttons: MessageDialog.Close
+ title: qsTr("Error")
+
+ onButtonClicked: errorNotification.close()
+ }
+
+ Component {
+ id: uriRecordDialog
+
+ ColumnLayout {
+ property alias uri: uriEditor.text
+ property int modelIndex: -1
+
+ ToolBar {
+ Layout.fillWidth: true
+
+ RowLayout {
+ anchors.fill: parent
+ ToolButton {
+ icon.name: "arrow_back"
+ onClicked: stack.pop()
+ }
+ Label {
+ text: qsTr("URI Record")
+ elide: Label.ElideRight
+ horizontalAlignment: Qt.AlignHCenter
+ verticalAlignment: Qt.AlignVCenter
+ Layout.fillWidth: true
+ }
+ ToolButton {
+ text: qsTr("Save")
+ onClicked: {
+ if (modelIndex < 0) {
+ messageModel.addUriRecord(uri)
+ } else {
+ messageModel.setTextData(modelIndex, uri)
+ }
+ stack.pop()
+ }
+ }
+ }
+ }
+
+ Pane {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ ColumnLayout {
+ anchors.fill: parent
+
+ TextField {
+ id: uriEditor
+ Layout.fillWidth: true
+ placeholderText: qsTr("https://qt.io")
+ inputMethodHints: Qt.ImhUrlCharactersOnly
+ }
+ Item {
+ Layout.fillHeight: true
+ }
+ }
+ }
+ }
+ }
+
+ Component {
+ id: textRecordDialog
+
+ ColumnLayout {
+ property alias text: textEditor.text
+ property int modelIndex: -1
+
+ ToolBar {
+ Layout.fillWidth: true
+
+ RowLayout {
+ anchors.fill: parent
+ ToolButton {
+ icon.name: "arrow_back"
+ onClicked: stack.pop()
+ }
+ Label {
+ text: qsTr("Text Record")
+ elide: Label.ElideRight
+ horizontalAlignment: Qt.AlignHCenter
+ verticalAlignment: Qt.AlignVCenter
+ Layout.fillWidth: true
+ }
+ ToolButton {
+ text: qsTr("Save")
+ onClicked: {
+ if (modelIndex < 0) {
+ messageModel.addTextRecord(textEditor.text)
+ } else {
+ messageModel.setTextData(modelIndex, textEditor.text)
+ }
+ stack.pop()
+ }
+ }
+ }
+ }
+
+ Pane {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ ScrollView {
+ anchors.fill: parent
+
+ TextArea {
+ id: textEditor
+ placeholderText: qsTr("Enter some text...")
+ Layout.fillWidth: true
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/examples/nfc/ndefeditor/NdefRecordDelegate.qml b/examples/nfc/ndefeditor/NdefRecordDelegate.qml
new file mode 100644
index 00000000..f01aff05
--- /dev/null
+++ b/examples/nfc/ndefeditor/NdefRecordDelegate.qml
@@ -0,0 +1,50 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+pragma ComponentBehavior: Bound
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+import NdefEditor
+
+SwipeDelegate {
+ required property int index
+ required property int recordType
+ required property string recordText
+
+ id: delegate
+
+ contentItem: ColumnLayout {
+ Label {
+ text: qsTr("Record %L1 - %2").arg(delegate.index + 1).arg(
+ delegate.describeRecordType(delegate.recordType))
+ font.bold: true
+ }
+
+ Label {
+ text: delegate.recordText
+ elide: Text.ElideRight
+ maximumLineCount: 1
+ Layout.fillWidth: true
+ }
+ }
+
+ swipe.left: Button {
+ text: qsTr("Delete")
+ padding: 12
+ height: delegate.height
+ anchors.left: delegate.left
+ SwipeDelegate.onClicked: delegate.deleteClicked()
+ }
+
+ function describeRecordType(type) {
+ switch (type) {
+ case NdefMessageModel.TextRecord: return qsTr("Text")
+ case NdefMessageModel.UriRecord: return qsTr("URI")
+ default: return qsTr("Other")
+ }
+ }
+
+ signal deleteClicked()
+}
diff --git a/examples/nfc/ndefeditor/android/AndroidManifest.xml b/examples/nfc/ndefeditor/android/AndroidManifest.xml
deleted file mode 100644
index ee3ae1b7..00000000
--- a/examples/nfc/ndefeditor/android/AndroidManifest.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0"?>
-<manifest package="org.qtproject.example" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="-- %%INSERT_VERSION_NAME%% --" android:versionCode="-- %%INSERT_VERSION_CODE%% --" android:installLocation="auto">
- <!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
- Remove the comment if you do not require these default permissions. -->
- <!-- %%INSERT_PERMISSIONS -->
-
- <!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
- Remove the comment if you do not require these default features. -->
- <!-- %%INSERT_FEATURES -->
-
- <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
- <application android:hardwareAccelerated="true" android:name="org.qtproject.qt.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --" android:extractNativeLibs="true" android:requestLegacyExternalStorage="true">
- <activity android:windowSoftInputMode="adjustResize" android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:name="org.qtproject.qt.android.bindings.QtActivity" android:label="-- %%INSERT_APP_NAME%% --" android:screenOrientation="unspecified" android:launchMode="singleTop">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
-
- <!-- Application arguments -->
- <meta-data android:name="android.app.arguments" android:value="-- %%INSERT_APP_ARGUMENTS%% --"/>
- <!-- Application arguments -->
-
- <meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
-
- <!-- Background running -->
- <!-- Warning: changing this value to true may cause unexpected crashes if the
- application still try to draw after
- "applicationStateChanged(Qt::ApplicationSuspended)"
- signal is sent! -->
- <meta-data android:name="android.app.background_running" android:value="false"/>
- <!-- Background running -->
-
- <!-- extract android style -->
- <!-- available android:values :
- * default - In most cases this will be the same as "full", but it can also be something else if needed, e.g., for compatibility reasons
- * full - useful QWidget & Quick Controls 1 apps
- * minimal - useful for Quick Controls 2 apps, it is much faster than "full"
- * none - useful for apps that don't use any of the above Qt modules
- -->
- <meta-data android:name="android.app.extract_android_style" android:value="default"/>
- <!-- extract android style -->
- </activity>
-
- <!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices -->
-
- </application>
-
-</manifest>
diff --git a/examples/nfc/ndefeditor/doc/images/ndefeditor.png b/examples/nfc/ndefeditor/doc/images/ndefeditor.png
index 9ce8ade5..2be32f60 100644
--- a/examples/nfc/ndefeditor/doc/images/ndefeditor.png
+++ b/examples/nfc/ndefeditor/doc/images/ndefeditor.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/doc/src/ndefeditor.qdoc b/examples/nfc/ndefeditor/doc/src/ndefeditor.qdoc
index 2448b3e5..48afc35d 100644
--- a/examples/nfc/ndefeditor/doc/src/ndefeditor.qdoc
+++ b/examples/nfc/ndefeditor/doc/src/ndefeditor.qdoc
@@ -8,78 +8,9 @@
The NDEF Editor example reads and writes NFC Data Exchange Format
(NDEF) messages to NFC Forum Tags. NDEF messages can be composed by
-adding records of supported types. Additionally, NDEF messages can be
-loaded/saved from/into a file located in the file system of the
-device where the application is running.
+adding text and URI records. Records can be deleted by swiping them to the left.
\image ndefeditor.png
-\section1 NFC Tag detection
-
-The \c MainWindow class is able to detect if an NFC Tag is in the range
-for read/write operations. It can also detect if the connection has been
-lost. This is achieved by connecting the \c MainWindow class private
-handlers to the \l QNearFieldManager::targetDetected and
-\l QNearFieldManager::targetLost signals.
-
-\snippet ndefeditor/mainwindow.cpp QNearFieldManager init
-
-When \e Read or \e Write button is pressed, the detection of NFC tags is started
-by calling the \l QNearFieldManager::startTargetDetection method.
-
-\snippet ndefeditor/mainwindow.cpp QNearFieldManager start detection
-
-Once the target is detected, the \c MainWindow connects the following
-signals to its internal private slots:
-\l QNearFieldTarget::ndefMessageRead, \l QNearFieldTarget::NdefReadError,
-\l QNearFieldTarget::requestCompleted,
-\l QNearFieldTarget::NdefWriteError and \l {QNearFieldTarget::error}.
-
-\snippet ndefeditor/mainwindow.cpp QNearFieldTarget detected
-
-If during the process of reading or writing to an NFC Tag the
-connection is lost, the \c MainWindow reacts to this event by
-scheduling the target deletion (using \l QObject::deleteLater).
-
-\snippet ndefeditor/mainwindow.cpp QNearFieldTarget lost
-
-\section1 Record creation
-
-The main window of the NDEF Editor example manages the composition and
-creation of NFC records. The UI contains a \l QScrollArea, which is used to
-dynamically add the record editors. The following methods of the \c MainWindow
-class provide an interface towards each of the record editing classes managing
-the different types of records.
-
-\snippet ndefeditor/mainwindow.h 0
-
-The following sections explain each of the record editing classes.
-
-\section1 Record editing classes
-
-\section2 TextRecordEditor
-
-The \c TextRecordEditor is a \l QWidget that allows to edit the contents of the
-NDEF Text record. A new instance of this class is created for each text record.
-
-\snippet ndefeditor/textrecordeditor.h 0
-
-\section2 UriRecordEditor
-
-The \c UriRecordEditor is a \l QWidget that allows to edit the contents of the
-NDEF Uri record. A new instance of this class is created for each uri record.
-
-\snippet ndefeditor/urirecordeditor.h 0
-
-\section2 MimeImageRecordEditor
-
-The \c MimeImageRecordEditor is a \l QWidget that allows to edit the contents of
-the NDEF MIME record. In this example MIME record can be used to store an icon.
-A new instance of this class is created for each MIME record.
-
-\snippet ndefeditor/mimeimagerecordeditor.h 0
-
-\include examples-run.qdocinc
-
\sa {Qt NFC}
*/
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20/add.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/add.png
new file mode 100644
index 00000000..49659bf3
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/add.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20/arrow_back.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/arrow_back.png
new file mode 100644
index 00000000..8d39f677
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/arrow_back.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20/file_download.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/file_download.png
new file mode 100644
index 00000000..405a67b0
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/file_download.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20/file_upload.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/file_upload.png
new file mode 100644
index 00000000..7a13c507
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/file_upload.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20/link.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/link.png
new file mode 100644
index 00000000..6d663387
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/link.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20/text_snippet.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/text_snippet.png
new file mode 100644
index 00000000..bada4338
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20/text_snippet.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/add.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/add.png
new file mode 100644
index 00000000..8114d615
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/add.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/arrow_back.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/arrow_back.png
new file mode 100644
index 00000000..843444e2
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/arrow_back.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/file_download.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/file_download.png
new file mode 100644
index 00000000..d848b217
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/file_download.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/file_upload.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/file_upload.png
new file mode 100644
index 00000000..22364309
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/file_upload.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/link.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/link.png
new file mode 100644
index 00000000..0567312a
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/link.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/text_snippet.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/text_snippet.png
new file mode 100644
index 00000000..96ab459a
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@2/text_snippet.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/add.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/add.png
new file mode 100644
index 00000000..c55d4144
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/add.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/arrow_back.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/arrow_back.png
new file mode 100644
index 00000000..bb620d68
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/arrow_back.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/file_download.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/file_download.png
new file mode 100644
index 00000000..db8e7b13
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/file_download.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/file_upload.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/file_upload.png
new file mode 100644
index 00000000..1b240284
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/file_upload.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/link.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/link.png
new file mode 100644
index 00000000..e0569cbb
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/link.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/text_snippet.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/text_snippet.png
new file mode 100644
index 00000000..9dc6683f
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@3/text_snippet.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/add.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/add.png
new file mode 100644
index 00000000..4813a26f
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/add.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/arrow_back.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/arrow_back.png
new file mode 100644
index 00000000..54354ddd
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/arrow_back.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/file_download.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/file_download.png
new file mode 100644
index 00000000..20148b92
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/file_download.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/file_upload.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/file_upload.png
new file mode 100644
index 00000000..22a98cc2
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/file_upload.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/link.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/link.png
new file mode 100644
index 00000000..f8bedeef
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/link.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/text_snippet.png b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/text_snippet.png
new file mode 100644
index 00000000..74a5f7fe
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/20x20@4/text_snippet.png
Binary files differ
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/index.theme b/examples/nfc/ndefeditor/icons/ndefeditor/index.theme
new file mode 100644
index 00000000..756b1232
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/index.theme
@@ -0,0 +1,22 @@
+[Icon Theme]
+Name=ndefeditor
+Directories=20x20,20x20@2,20x20@3,20x20@4
+
+[20x20]
+Size=20
+Type=Fixed
+
+[20x20@2]
+Size=20
+Scale=2
+Type=Fixed
+
+[20x20@3]
+Size=20
+Scale=3
+Type=Fixed
+
+[20x20@4]
+Size=20
+Scale=4
+Type=Fixed
diff --git a/examples/nfc/ndefeditor/icons/ndefeditor/qt_attribution.json b/examples/nfc/ndefeditor/icons/ndefeditor/qt_attribution.json
new file mode 100644
index 00000000..974e9dbc
--- /dev/null
+++ b/examples/nfc/ndefeditor/icons/ndefeditor/qt_attribution.json
@@ -0,0 +1,11 @@
+{
+ "Id": "ndefeditor",
+ "Name": "Selected Material Icons",
+ "QDocModule": "qtconnectivity",
+ "QtUsage": "Used in NDEF Editor Example for QtNfc.",
+ "Files": "*/*.png",
+ "Homepage": "https://fonts.google.com/icons",
+ "License": "Apache License Version 2.0",
+ "LicenseId": "Apache-2.0",
+ "Copyright": "Copyright 2018 Google, Inc. All Rights Reserved."
+}
diff --git a/examples/nfc/ndefeditor/main.cpp b/examples/nfc/ndefeditor/main.cpp
index f76d38b4..a9e5218d 100644
--- a/examples/nfc/ndefeditor/main.cpp
+++ b/examples/nfc/ndefeditor/main.cpp
@@ -1,15 +1,22 @@
-// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-#include <QApplication>
-#include "mainwindow.h"
+#include <QGuiApplication>
+#include <QIcon>
+#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
- QApplication a(argc, argv);
- MainWindow w;
+ QGuiApplication app(argc, argv);
- w.show();
+ QIcon::setThemeName("ndefeditor");
- return a.exec();
+ QQmlApplicationEngine engine;
+
+ QObject::connect(
+ &engine, &QQmlApplicationEngine::objectCreationFailed, &app,
+ []() { QCoreApplication::exit(1); }, Qt::QueuedConnection);
+ engine.loadFromModule("NdefEditor", "Main");
+
+ return app.exec();
}
diff --git a/examples/nfc/ndefeditor/mainwindow.cpp b/examples/nfc/ndefeditor/mainwindow.cpp
deleted file mode 100644
index aa5b79a0..00000000
--- a/examples/nfc/ndefeditor/mainwindow.cpp
+++ /dev/null
@@ -1,376 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#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>
-#include <QtWidgets/QScroller>
-#include <QtWidgets/QApplication>
-#include <QtGui/QScreen>
-
-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"));
-
- vbox->addWidget(recordEditor);
-
- if (!record.isEmpty())
- recordEditor->setRecord(record);
-}
-
-MainWindow::MainWindow(QWidget *parent)
-: QMainWindow(parent), ui(new Ui::MainWindow), m_touchAction(NoAction)
-{
- ui->setupUi(this);
-
- connect(ui->addRecord, &QPushButton::clicked, this, &MainWindow::showMenu);
-
- QVBoxLayout *vbox = new QVBoxLayout;
- ui->scrollAreaWidgetContents->setLayout(vbox);
-#if (defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)) || defined(Q_OS_IOS)
- QScroller::grabGesture(ui->scrollArea, QScroller::TouchGesture);
- ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
-#endif
-
- // Detect keyboard show/hide. We can't directly update the UI to ensure
- // that the focused widget is active. Instead we wait for a resizeEvent
- // that happens shortly after the keyboard is shown, and do all the
- // processing there.
- QInputMethod *inputMethod = qApp->inputMethod();
- connect(inputMethod, &QInputMethod::visibleChanged,
- [this, inputMethod]() { m_keyboardVisible = inputMethod->isVisible(); });
-
- //! [QNearFieldManager init]
- m_manager = new QNearFieldManager(this);
- connect(m_manager, &QNearFieldManager::targetDetected,
- this, &MainWindow::targetDetected);
- connect(m_manager, &QNearFieldManager::targetLost,
- this, &MainWindow::targetLost);
- //! [QNearFieldManager init]
-}
-
-MainWindow::~MainWindow()
-{
- delete ui;
-}
-
-void MainWindow::resizeEvent(QResizeEvent *e)
-{
- QMainWindow::resizeEvent(e);
- if (m_keyboardVisible) {
- QWidget *areaWidget = ui->scrollAreaWidgetContents;
- QList<QWidget *> childWidgets = areaWidget->findChildren<QWidget *>();
- for (const auto widget : childWidgets) {
- if (widget->hasFocus()) {
- ui->scrollArea->ensureWidgetVisible(widget);
- }
- }
- }
-}
-
-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;
-
- //! [QNearFieldManager start detection]
- m_manager->startTargetDetection(QNearFieldTarget::NdefAccess);
- //! [QNearFieldManager start detection]
-}
-
-void MainWindow::touchStore()
-{
- ui->status->setStyleSheet(QStringLiteral("background: yellow"));
-
- m_touchAction = WriteNdef;
-
- m_manager->startTargetDetection(QNearFieldTarget::NdefAccess);
-}
-
-//! [QNearFieldTarget detected]
-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::requestCompleted, 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;
- }
-}
-//! [QNearFieldTarget detected]
-
-//! [QNearFieldTarget lost]
-void MainWindow::targetLost(QNearFieldTarget *target)
-{
- target->deleteLater();
-}
-//! [QNearFieldTarget lost]
-
-void MainWindow::ndefMessageRead(const QNdefMessage &message)
-{
- clearMessage();
-
- for (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());
- //! [QNearFieldManager stop detection]
- m_manager->stopTargetDetection();
- //! [QNearFieldManager stop detection]
- m_request = QNearFieldTarget::RequestId();
- ui->statusBar->clearMessage();
-}
-
-void MainWindow::ndefMessageWritten(const QNearFieldTarget::RequestId &id)
-{
- if (id == m_request) {
- ui->status->setStyleSheet(QString());
- 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->stopTargetDetection();
- m_request = QNearFieldTarget::RequestId();
- }
-}
-
-void MainWindow::showMenu()
-{
- // We have to manually call QMenu::popup() because of QTBUG-98651.
- // And we need to re-create menu each time because of QTBUG-97482.
- if (m_menu) {
- m_menu->setParent(nullptr);
- delete m_menu;
- }
- m_menu = new QMenu(this);
- m_menu->addAction(tr("NFC Text Record"), this, &MainWindow::addNfcTextRecord);
- m_menu->addAction(tr("NFC URI Record"), this, &MainWindow::addNfcUriRecord);
- m_menu->addAction(tr("MIME Image Record"), this, &MainWindow::addMimeImageRecord);
- m_menu->addAction(tr("Empty Record"), this, &MainWindow::addEmptyRecord);
-
- // Use menu's sizeHint() to position it so that its right side is aligned
- // with button's right side.
- QPushButton *button = ui->addRecord;
- const int x = button->x() + button->width() - m_menu->sizeHint().width();
- const int y = button->y() + button->height();
- m_menu->popup(mapToGlobal(QPoint(x, y)));
-}
-
-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"
diff --git a/examples/nfc/ndefeditor/mainwindow.h b/examples/nfc/ndefeditor/mainwindow.h
deleted file mode 100644
index 8a60a1a1..00000000
--- a/examples/nfc/ndefeditor/mainwindow.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#ifndef MAINWINDOW_H
-#define MAINWINDOW_H
-
-#include <QtNfc/qnearfieldtarget.h>
-
-#include <QtWidgets/QMainWindow>
-
-QT_FORWARD_DECLARE_CLASS(QNearFieldManager)
-QT_FORWARD_DECLARE_CLASS(QNdefMessage)
-QT_FORWARD_DECLARE_CLASS(QScreen)
-QT_FORWARD_DECLARE_CLASS(QMenu)
-
-QT_BEGIN_NAMESPACE
-namespace Ui {
- class MainWindow;
-}
-QT_END_NAMESPACE
-
-class MainWindow : public QMainWindow
-{
- Q_OBJECT
-
-public:
- explicit MainWindow(QWidget *parent = 0);
- ~MainWindow();
-
-protected:
- void resizeEvent(QResizeEvent *e) override;
-
-private slots:
- //! [0]
- void addNfcTextRecord();
- void addNfcUriRecord();
- void addMimeImageRecord();
- void addEmptyRecord();
- //! [0]
- void clearMessage();
-
- void loadMessage();
- void saveMessage();
-
- void touchReceive();
- void touchStore();
-
- void targetDetected(QNearFieldTarget *target);
- void targetLost(QNearFieldTarget *target);
-
- void ndefMessageRead(const QNdefMessage &message);
- void ndefMessageWritten(const QNearFieldTarget::RequestId &id);
- void targetError(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id);
-
- void showMenu();
-
-private:
- enum TouchAction {
- NoAction,
- ReadNdef,
- WriteNdef
- };
-
- QNdefMessage ndefMessage() const;
- void handleScreenChange();
- void updateWidgetLayout(Qt::ScreenOrientation orientation);
-
-private:
- Ui::MainWindow *ui;
- QMenu *m_menu = nullptr;
-
- QNearFieldManager *m_manager;
- TouchAction m_touchAction;
- QNearFieldTarget::RequestId m_request;
- bool m_keyboardVisible = false;
- QScreen *m_screen = nullptr;
-};
-
-#endif // MAINWINDOW_H
diff --git a/examples/nfc/ndefeditor/mainwindow.ui b/examples/nfc/ndefeditor/mainwindow.ui
deleted file mode 100644
index cb8c2c35..00000000
--- a/examples/nfc/ndefeditor/mainwindow.ui
+++ /dev/null
@@ -1,225 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>559</width>
- <height>397</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>NDEF Message Editor</string>
- </property>
- <widget class="QWidget" name="centralWidget">
- <layout class="QVBoxLayout" name="verticalLayout">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <property name="leftMargin">
- <number>9</number>
- </property>
- <property name="rightMargin">
- <number>9</number>
- </property>
- <item>
- <widget class="QWidget" name="status" native="true">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>25</width>
- <height>25</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>25</width>
- <height>25</height>
- </size>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="touchRetrieve">
- <property name="text">
- <string>Read</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="touchStore">
- <property name="text">
- <string>Write</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="loadMessage">
- <property name="text">
- <string>Load</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="saveMessage">
- <property name="text">
- <string>Save</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="clearMessage">
- <property name="text">
- <string>Clear</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="addRecord">
- <property name="text">
- <string>Add</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QScrollArea" name="scrollArea">
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Plain</enum>
- </property>
- <property name="verticalScrollBarPolicy">
- <enum>Qt::ScrollBarAsNeeded</enum>
- </property>
- <property name="horizontalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOff</enum>
- </property>
- <property name="widgetResizable">
- <bool>true</bool>
- </property>
- <widget class="QWidget" name="scrollAreaWidgetContents">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>559</width>
- <height>327</height>
- </rect>
- </property>
- </widget>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QStatusBar" name="statusBar"/>
- </widget>
- <layoutdefault spacing="6" margin="11"/>
- <resources/>
- <connections>
- <connection>
- <sender>saveMessage</sender>
- <signal>clicked()</signal>
- <receiver>MainWindow</receiver>
- <slot>saveMessage()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>419</x>
- <y>47</y>
- </hint>
- <hint type="destinationlabel">
- <x>275</x>
- <y>198</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>touchRetrieve</sender>
- <signal>clicked()</signal>
- <receiver>MainWindow</receiver>
- <slot>touchReceive()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>142</x>
- <y>47</y>
- </hint>
- <hint type="destinationlabel">
- <x>275</x>
- <y>198</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>touchStore</sender>
- <signal>clicked()</signal>
- <receiver>MainWindow</receiver>
- <slot>touchStore()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>244</x>
- <y>47</y>
- </hint>
- <hint type="destinationlabel">
- <x>275</x>
- <y>198</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>loadMessage</sender>
- <signal>clicked()</signal>
- <receiver>MainWindow</receiver>
- <slot>loadMessage()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>334</x>
- <y>47</y>
- </hint>
- <hint type="destinationlabel">
- <x>275</x>
- <y>198</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>clearMessage</sender>
- <signal>clicked()</signal>
- <receiver>MainWindow</receiver>
- <slot>clearMessage()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>419</x>
- <y>22</y>
- </hint>
- <hint type="destinationlabel">
- <x>275</x>
- <y>198</y>
- </hint>
- </hints>
- </connection>
- </connections>
- <slots>
- <slot>saveMessage()</slot>
- <slot>loadMessage()</slot>
- <slot>touchReceive()</slot>
- <slot>touchStore()</slot>
- <slot>clearMessage()</slot>
- </slots>
-</ui>
diff --git a/examples/nfc/ndefeditor/mimeimagerecordeditor.cpp b/examples/nfc/ndefeditor/mimeimagerecordeditor.cpp
deleted file mode 100644
index a5109757..00000000
--- a/examples/nfc/ndefeditor/mimeimagerecordeditor.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#include "mimeimagerecordeditor.h"
-#include "ui_mimeimagerecordeditor.h"
-
-#include <QtGui/QImageReader>
-#include <QtWidgets/QFileDialog>
-#include <QtCore/QBuffer>
-#include <QScreen>
-#include <QLayout>
-
-#if (defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)) || defined(Q_OS_IOS)
-# define MOBILE_PLATFORM
-#endif
-
-static QString imageFormatToMimeType(const QByteArray &format)
-{
- if (format == "bmp")
- return QStringLiteral("image/bmp");
- else if (format == "gif")
- return QStringLiteral("image/gif");
- else if (format == "jpg" || format == "jpeg")
- return QStringLiteral("image/jpeg");
- else if (format == "mng")
- return QStringLiteral("video/x-mng");
- else if (format == "png")
- return QStringLiteral("image/png");
- else if (format == "pbm")
- return QStringLiteral("image/x-portable-bitmap");
- else if (format == "pgm")
- return QStringLiteral("image/x-portable-graymap");
- else if (format == "ppm")
- return QStringLiteral("image/x-portable-pixmap");
- else if (format == "tiff")
- return QStringLiteral("image/tiff");
- else if (format == "xbm")
- return QStringLiteral("image/x-xbitmap");
- else if (format == "xpm")
- return QStringLiteral("image/x-xpixmap");
- else if (format == "svg")
- return QStringLiteral("image/svg+xml");
- else
- return QString();
-}
-
-MimeImageRecordEditor::MimeImageRecordEditor(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::MimeImageRecordEditor)
-{
- ui->setupUi(this);
-#ifdef MOBILE_PLATFORM
- connect(screen(), &QScreen::orientationChanged, this,
- &MimeImageRecordEditor::handleScreenOrientationChange);
-#endif
-}
-
-MimeImageRecordEditor::~MimeImageRecordEditor()
-{
- delete ui;
-}
-
-void MimeImageRecordEditor::setRecord(const QNdefRecord &record)
-{
- m_record = record;
-
- QByteArray data = record.payload();
- QBuffer buffer(&data);
- buffer.open(QIODevice::ReadOnly);
-
- QImageReader reader(&buffer);
-
- ui->mimeImageType->setText(imageFormatToMimeType(reader.format()));
- ui->mimeImageFile->clear();
-
- m_pixmap = QPixmap::fromImage(reader.read());
- updatePixmap();
-}
-
-QNdefRecord MimeImageRecordEditor::record() const
-{
- return m_record;
-}
-
-void MimeImageRecordEditor::handleScreenOrientationChange(Qt::ScreenOrientation orientation)
-{
- Q_UNUSED(orientation);
-#ifdef MOBILE_PLATFORM
- if (m_imageSelected) {
- ui->mimeImageImage->clear();
- adjustSize();
- m_screenRotated = true;
- }
-#endif
-}
-
-void MimeImageRecordEditor::resizeEvent(QResizeEvent *)
-{
- if (m_imageSelected) {
-#ifdef MOBILE_PLATFORM
- if (m_screenRotated) {
- updatePixmap();
- m_screenRotated = false;
- }
-#else
- updatePixmap();
-#endif
- }
-}
-
-void MimeImageRecordEditor::updatePixmap()
-{
- // Calculate the desired width of the image. It's calculated based on the
- // screen size minus the content margins.
- const auto parentContentMargins = parentWidget()->layout()->contentsMargins();
- const auto thisContentMargins = layout()->contentsMargins();
-#ifdef MOBILE_PLATFORM
- // Because of QTBUG-94459 the screen size might be incorrect, so we check
- // the orientation to find the actual width
- const auto w = screen()->availableSize().width();
- const auto h = screen()->availableSize().height();
- const auto screenWidth =
- (screen()->orientation() == Qt::PortraitOrientation) ? qMin(w, h) : qMax(w, h);
-#else
- const auto screenWidth = width();
-#endif
- const auto imageWidth = screenWidth - parentContentMargins.right() - parentContentMargins.left()
- - thisContentMargins.right() - thisContentMargins.left();
-
- if (!m_pixmap.isNull()) {
- if (m_pixmap.width() > imageWidth)
- ui->mimeImageImage->setPixmap(m_pixmap.scaledToWidth(imageWidth));
- else
- ui->mimeImageImage->setPixmap(m_pixmap);
- } else {
- ui->mimeImageImage->setText("Can't show the image");
- }
-}
-
-void MimeImageRecordEditor::on_mimeImageOpen_clicked()
-{
- QString mimeDataFile = QFileDialog::getOpenFileName(this, tr("Select Image File"));
- if (mimeDataFile.isEmpty())
- return;
-
- QFile imageFile(mimeDataFile);
- if (!imageFile.open(QIODevice::ReadOnly)) {
- ui->mimeImageFile->clear();
- ui->mimeImageImage->clear();
- }
-
- QByteArray imageData = imageFile.readAll();
-
- QBuffer buffer(&imageData);
- buffer.open(QIODevice::ReadOnly);
-
- QImageReader reader(&buffer);
- QString mimeType = imageFormatToMimeType(reader.format());
- ui->mimeImageType->setText(mimeType);
-
- ui->mimeImageFile->setText(mimeDataFile);
- const QImage image = reader.read();
- m_pixmap = QPixmap::fromImage(image);
- m_imageSelected = true;
- updatePixmap();
-
- m_record.setTypeNameFormat(QNdefRecord::Mime);
- m_record.setType(mimeType.toLatin1());
- m_record.setPayload(imageData);
-}
diff --git a/examples/nfc/ndefeditor/mimeimagerecordeditor.h b/examples/nfc/ndefeditor/mimeimagerecordeditor.h
deleted file mode 100644
index 80c79c00..00000000
--- a/examples/nfc/ndefeditor/mimeimagerecordeditor.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#ifndef MIMEIMAGERECORDEDITOR_H
-#define MIMEIMAGERECORDEDITOR_H
-
-#include <QtNfc/qndefrecord.h>
-
-#include <QtWidgets/QWidget>
-
-QT_USE_NAMESPACE
-
-QT_BEGIN_NAMESPACE
-namespace Ui {
- class MimeImageRecordEditor;
-}
-QT_END_NAMESPACE
-
-//! [0]
-class MimeImageRecordEditor : public QWidget
-{
- Q_OBJECT
-
-public:
- explicit MimeImageRecordEditor(QWidget *parent = 0);
- ~MimeImageRecordEditor();
-
- void setRecord(const QNdefRecord &record);
- QNdefRecord record() const;
-
-public slots:
- void handleScreenOrientationChange(Qt::ScreenOrientation orientation);
-
-protected:
- void resizeEvent(QResizeEvent *) override;
-
-private:
- void updatePixmap();
-
- Ui::MimeImageRecordEditor *ui;
- QNdefRecord m_record;
- QPixmap m_pixmap;
- bool m_imageSelected = false;
- bool m_screenRotated = false;
-
-private slots:
- void on_mimeImageOpen_clicked();
-};
-//! [0]
-#endif // MIMEIMAGERECORDEDITOR_H
diff --git a/examples/nfc/ndefeditor/mimeimagerecordeditor.ui b/examples/nfc/ndefeditor/mimeimagerecordeditor.ui
deleted file mode 100644
index 6403972b..00000000
--- a/examples/nfc/ndefeditor/mimeimagerecordeditor.ui
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MimeImageRecordEditor</class>
- <widget class="QWidget" name="MimeImageRecordEditor">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>403</width>
- <height>126</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Form</string>
- </property>
- <layout class="QFormLayout" name="formLayout">
- <item row="0" column="0" colspan="2">
- <widget class="QLabel" name="label_4">
- <property name="text">
- <string>MIME Record &lt;image/*&gt;</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_11">
- <property name="text">
- <string>Type:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLabel" name="mimeImageType">
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>image/</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_12">
- <property name="text">
- <string>File:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QLineEdit" name="mimeImageFile">
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="mimeImageOpen">
- <property name="text">
- <string>...</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item row="3" column="0" colspan="2">
- <widget class="QLabel" name="mimeImageImage">
- <property name="text">
- <string>Select an image</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/examples/nfc/ndefeditor/ndefeditor.pro b/examples/nfc/ndefeditor/ndefeditor.pro
index 1ab9724a..5e2a80c7 100644
--- a/examples/nfc/ndefeditor/ndefeditor.pro
+++ b/examples/nfc/ndefeditor/ndefeditor.pro
@@ -1,36 +1,66 @@
-QT += nfc widgets
-requires(qtConfig(filedialog))
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+QT += nfc quick quickcontrols2
+
+CONFIG += qmltypes
+QML_IMPORT_NAME = NdefEditor
+QML_IMPORT_MAJOR_VERSION = 1
TARGET = ndefeditor
TEMPLATE = app
SOURCES += \
main.cpp \
- mainwindow.cpp \
- textrecordeditor.cpp \
- urirecordeditor.cpp \
- mimeimagerecordeditor.cpp
+ nfcmanager.cpp \
+ nfctarget.cpp \
+ ndefmessagemodel.cpp
HEADERS += \
- mainwindow.h \
- textrecordeditor.h \
- urirecordeditor.h \
- mimeimagerecordeditor.h
+ nfcmanager.h \
+ nfctarget.h \
+ ndefmessagemodel.h
+
+qml_resources.files = \
+ qmldir \
+ Main.qml \
+ MainWindow.qml \
+ NdefRecordDelegate.qml
+
+qml_resources.prefix = /qt/qml/NdefEditor
-ios: QMAKE_INFO_PLIST = Info.plist
+theme_resources.files = \
+ icons/ndefeditor/20x20@2/add.png \
+ icons/ndefeditor/20x20@2/arrow_back.png \
+ icons/ndefeditor/20x20@2/file_download.png \
+ icons/ndefeditor/20x20@2/file_upload.png \
+ icons/ndefeditor/20x20@2/link.png \
+ icons/ndefeditor/20x20@2/text_snippet.png \
+ icons/ndefeditor/20x20@3/add.png \
+ icons/ndefeditor/20x20@3/arrow_back.png \
+ icons/ndefeditor/20x20@3/file_download.png \
+ icons/ndefeditor/20x20@3/file_upload.png \
+ icons/ndefeditor/20x20@3/link.png \
+ icons/ndefeditor/20x20@3/text_snippet.png \
+ icons/ndefeditor/20x20@4/add.png \
+ icons/ndefeditor/20x20@4/arrow_back.png \
+ icons/ndefeditor/20x20@4/file_download.png \
+ icons/ndefeditor/20x20@4/file_upload.png \
+ icons/ndefeditor/20x20@4/link.png \
+ icons/ndefeditor/20x20@4/text_snippet.png \
+ icons/ndefeditor/20x20/add.png \
+ icons/ndefeditor/20x20/arrow_back.png \
+ icons/ndefeditor/20x20/file_download.png \
+ icons/ndefeditor/20x20/file_upload.png \
+ icons/ndefeditor/20x20/link.png \
+ icons/ndefeditor/20x20/text_snippet.png \
+ icons/ndefeditor/index.theme
-FORMS += \
- mainwindow.ui \
- textrecordeditor.ui \
- urirecordeditor.ui \
- mimeimagerecordeditor.ui
+theme_resources.prefix = /
-android {
- ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
+RESOURCES += qml_resources theme_resources
- DISTFILES += \
- android/AndroidManifest.xml
-}
+ios: QMAKE_INFO_PLIST = Info.qmake.plist
target.path = $$[QT_INSTALL_EXAMPLES]/nfc/ndefeditor
INSTALLS += target
diff --git a/examples/nfc/ndefeditor/ndefmessagemodel.cpp b/examples/nfc/ndefeditor/ndefmessagemodel.cpp
new file mode 100644
index 00000000..177d21dc
--- /dev/null
+++ b/examples/nfc/ndefeditor/ndefmessagemodel.cpp
@@ -0,0 +1,156 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "ndefmessagemodel.h"
+
+#include <QNdefNfcTextRecord>
+#include <QNdefNfcUriRecord>
+
+NdefMessageModel::NdefMessageModel(QObject *parent) : QAbstractListModel(parent) { }
+
+int NdefMessageModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ return m_message.size();
+}
+
+static NdefMessageModel::RecordType getRecordType(const QNdefRecord &record)
+{
+ if (record.isRecordType<QNdefNfcTextRecord>()) {
+ return NdefMessageModel::TextRecord;
+ } else if (record.isRecordType<QNdefNfcUriRecord>()) {
+ return NdefMessageModel::UriRecord;
+ }
+ return NdefMessageModel::OtherRecord;
+}
+
+static QString getText(const QNdefRecord &record)
+{
+ if (record.isRecordType<QNdefNfcTextRecord>()) {
+ QNdefNfcTextRecord r(record);
+ return r.text();
+ } else if (record.isRecordType<QNdefNfcUriRecord>()) {
+ QNdefNfcUriRecord r(record);
+ return r.uri().toString();
+ }
+ return record.payload().toHex(':');
+}
+
+QVariant NdefMessageModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return {};
+
+ if (index.row() < 0 || index.row() >= m_message.size())
+ return {};
+
+ const auto &record = m_message.at(index.row());
+
+ switch (role) {
+ case RecordTypeRole:
+ return getRecordType(record);
+ case RecordTextRole:
+ return getText(record);
+ default:
+ return {};
+ }
+}
+
+QHash<int, QByteArray> NdefMessageModel::roleNames() const
+{
+ QHash<int, QByteArray> names;
+ names[RecordTypeRole] = "recordType";
+ names[RecordTextRole] = "recordText";
+ return names;
+}
+
+bool NdefMessageModel::removeRows(int row, int count, const QModelIndex &parent)
+{
+ if (parent.isValid())
+ return false;
+ if (row < 0 || count <= 0)
+ return false;
+ if (row >= m_message.size() || (m_message.size() - row) < count)
+ return false;
+
+ beginRemoveRows(parent, row, row + count - 1);
+ m_message.remove(row, count);
+ endRemoveRows();
+ Q_EMIT messageChanged();
+
+ return true;
+}
+
+QNdefMessage NdefMessageModel::message() const
+{
+ return m_message;
+}
+
+void NdefMessageModel::setMessage(const QNdefMessage &newMessage)
+{
+ if (m_message == newMessage)
+ return;
+
+ beginResetModel();
+ m_message = newMessage;
+ endResetModel();
+
+ Q_EMIT messageChanged();
+}
+
+void NdefMessageModel::clearMessage()
+{
+ if (m_message.isEmpty())
+ return;
+ removeRows(0, m_message.size(), {});
+}
+
+void NdefMessageModel::addTextRecord(const QString &text)
+{
+ QNdefNfcTextRecord record;
+ record.setText(text);
+
+ const auto newRow = m_message.size();
+ beginInsertRows({}, newRow, newRow);
+ m_message.append(std::move(record));
+ endInsertRows();
+ Q_EMIT messageChanged();
+}
+
+void NdefMessageModel::addUriRecord(const QString &uri)
+{
+ QNdefNfcUriRecord record;
+ record.setUri(QUrl(uri));
+
+ const auto newRow = m_message.size();
+ beginInsertRows({}, newRow, newRow);
+ m_message.append(std::move(record));
+ endInsertRows();
+ Q_EMIT messageChanged();
+}
+
+void NdefMessageModel::setTextData(int row, const QString &text)
+{
+ if (row < 0 || row >= m_message.size())
+ return;
+
+ const auto &record = m_message.at(row);
+
+ if (record.isRecordType<QNdefNfcTextRecord>()) {
+ QNdefNfcTextRecord r(record);
+ r.setText(text);
+ m_message[row] = r;
+ } else if (record.isRecordType<QNdefNfcUriRecord>()) {
+ QNdefNfcUriRecord r(record);
+ r.setUri(text);
+ m_message[row] = r;
+ } else {
+ return;
+ }
+
+ const auto idx = index(row);
+ Q_EMIT dataChanged(idx, idx, { RecordTextRole });
+ Q_EMIT messageChanged();
+}
diff --git a/examples/nfc/ndefeditor/ndefmessagemodel.h b/examples/nfc/ndefeditor/ndefmessagemodel.h
new file mode 100644
index 00000000..5f9ddf24
--- /dev/null
+++ b/examples/nfc/ndefeditor/ndefmessagemodel.h
@@ -0,0 +1,53 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef NDEFMESSAGEMODEL_H
+#define NDEFMESSAGEMODEL_H
+
+#include <QAbstractListModel>
+
+#include <QNdefMessage>
+#include <QQmlEngine>
+
+class NdefMessageModel : public QAbstractListModel
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(QNdefMessage message READ message WRITE setMessage NOTIFY messageChanged)
+
+public:
+ explicit NdefMessageModel(QObject *parent = nullptr);
+
+ enum Role {
+ RecordTypeRole,
+ RecordTextRole,
+ };
+
+ enum RecordType {
+ OtherRecord,
+ TextRecord,
+ UriRecord,
+ };
+ Q_ENUM(RecordType)
+
+ int rowCount(const QModelIndex &parent) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+ QHash<int, QByteArray> roleNames() const override;
+ bool removeRows(int row, int count, const QModelIndex &parent) override;
+
+ QNdefMessage message() const;
+ void setMessage(const QNdefMessage &newMessage);
+
+ Q_INVOKABLE void clearMessage();
+ Q_INVOKABLE void addTextRecord(const QString &text);
+ Q_INVOKABLE void addUriRecord(const QString &uri);
+ Q_INVOKABLE void setTextData(int row, const QString &text);
+
+Q_SIGNALS:
+ void messageChanged();
+
+private:
+ QNdefMessage m_message;
+};
+
+#endif // NDEFMESSAGEMODEL_H
diff --git a/examples/nfc/ndefeditor/nfcmanager.cpp b/examples/nfc/ndefeditor/nfcmanager.cpp
new file mode 100644
index 00000000..bc09b89e
--- /dev/null
+++ b/examples/nfc/ndefeditor/nfcmanager.cpp
@@ -0,0 +1,29 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "nfcmanager.h"
+
+#include <QNearFieldManager>
+
+#include "nfctarget.h"
+
+NfcManager::NfcManager(QObject *parent) : QObject(parent)
+{
+ m_manager = new QNearFieldManager(this);
+
+ connect(m_manager, &QNearFieldManager::targetDetected, this, [this](QNearFieldTarget *target) {
+ auto jsTarget = new NfcTarget(target);
+ QJSEngine::setObjectOwnership(jsTarget, QJSEngine::JavaScriptOwnership);
+ Q_EMIT targetDetected(jsTarget);
+ });
+}
+
+void NfcManager::startTargetDetection()
+{
+ m_manager->startTargetDetection(QNearFieldTarget::NdefAccess);
+}
+
+void NfcManager::stopTargetDetection()
+{
+ m_manager->stopTargetDetection();
+}
diff --git a/examples/nfc/ndefeditor/nfcmanager.h b/examples/nfc/ndefeditor/nfcmanager.h
new file mode 100644
index 00000000..b30f6f36
--- /dev/null
+++ b/examples/nfc/ndefeditor/nfcmanager.h
@@ -0,0 +1,33 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef NFCMANAGER_H
+#define NFCMANAGER_H
+
+#include <QObject>
+
+#include <QQmlEngine>
+
+#include "nfctarget.h"
+
+QT_FORWARD_DECLARE_CLASS(QNearFieldManager);
+
+class NfcManager : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+public:
+ explicit NfcManager(QObject *parent = nullptr);
+
+ Q_INVOKABLE void startTargetDetection();
+ Q_INVOKABLE void stopTargetDetection();
+
+Q_SIGNALS:
+ void targetDetected(NfcTarget *target);
+
+private:
+ QNearFieldManager *m_manager;
+};
+
+#endif // NFCMANAGER_H
diff --git a/examples/nfc/ndefeditor/nfctarget.cpp b/examples/nfc/ndefeditor/nfctarget.cpp
new file mode 100644
index 00000000..68b26df5
--- /dev/null
+++ b/examples/nfc/ndefeditor/nfctarget.cpp
@@ -0,0 +1,31 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "nfctarget.h"
+
+NfcTarget::NfcTarget(QNearFieldTarget *target, QObject *parent) : QObject(parent), m_target(target)
+{
+ target->setParent(this);
+
+ connect(target, &QNearFieldTarget::ndefMessageRead, this, &NfcTarget::ndefMessageRead);
+ connect(target, &QNearFieldTarget::requestCompleted, this, &NfcTarget::requestCompleted);
+ connect(target, &QNearFieldTarget::error, this, &NfcTarget::error);
+}
+
+bool NfcTarget::readNdefMessages()
+{
+ if (m_target.isNull())
+ return false;
+
+ auto req = m_target->readNdefMessages();
+ return req.isValid();
+}
+
+bool NfcTarget::writeNdefMessage(const QNdefMessage &message)
+{
+ if (m_target.isNull())
+ return false;
+
+ auto req = m_target->writeNdefMessages({ message });
+ return req.isValid();
+}
diff --git a/examples/nfc/ndefeditor/nfctarget.h b/examples/nfc/ndefeditor/nfctarget.h
new file mode 100644
index 00000000..8631687c
--- /dev/null
+++ b/examples/nfc/ndefeditor/nfctarget.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef NFCTARGET_H
+#define NFCTARGET_H
+
+#include <QObject>
+
+#include <QNdefMessage>
+#include <QNearFieldTarget>
+#include <QQmlEngine>
+
+class NfcTarget : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_UNCREATABLE("Created by NfcManager")
+
+public:
+ explicit NfcTarget(QNearFieldTarget *target, QObject *parent = nullptr);
+
+ Q_INVOKABLE bool readNdefMessages();
+ Q_INVOKABLE bool writeNdefMessage(const QNdefMessage &message);
+
+Q_SIGNALS:
+ void ndefMessageRead(const QNdefMessage &message);
+ void requestCompleted();
+ void error(QNearFieldTarget::Error error);
+
+private:
+ QPointer<QNearFieldTarget> m_target;
+};
+
+#endif // NFCTARGET_H
diff --git a/examples/nfc/ndefeditor/qmldir b/examples/nfc/ndefeditor/qmldir
new file mode 100644
index 00000000..0a77d792
--- /dev/null
+++ b/examples/nfc/ndefeditor/qmldir
@@ -0,0 +1,5 @@
+module NdefEditor
+prefer :/qt/qml/NdefEditor/
+Main 1.0 Main.qml
+MainWindow 1.0 MainWindow.qml
+NdefRecordDelegate 1.0 NdefRecordDelegate.qml
diff --git a/examples/nfc/ndefeditor/textrecordeditor.cpp b/examples/nfc/ndefeditor/textrecordeditor.cpp
deleted file mode 100644
index 0657a212..00000000
--- a/examples/nfc/ndefeditor/textrecordeditor.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#include "textrecordeditor.h"
-#include "ui_textrecordeditor.h"
-
-TextRecordEditor::TextRecordEditor(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::TextRecordEditor)
-{
- ui->setupUi(this);
-}
-
-TextRecordEditor::~TextRecordEditor()
-{
- delete ui;
-}
-
-void TextRecordEditor::setRecord(const QNdefNfcTextRecord &textRecord)
-{
- ui->text->setText(textRecord.text());
- ui->locale->setText(textRecord.locale());
-
- if (textRecord.encoding() == QNdefNfcTextRecord::Utf8)
- ui->encoding->setCurrentIndex(0);
- else if (textRecord.encoding() == QNdefNfcTextRecord::Utf16)
- ui->encoding->setCurrentIndex(1);
-}
-
-QNdefNfcTextRecord TextRecordEditor::record() const
-{
- QNdefNfcTextRecord record;
-
- if (ui->encoding->currentIndex() == 0)
- record.setEncoding(QNdefNfcTextRecord::Utf8);
- else if (ui->encoding->currentIndex() == 1)
- record.setEncoding(QNdefNfcTextRecord::Utf16);
-
- record.setLocale(ui->locale->text());
-
- record.setText(ui->text->text());
-
- return record;
-}
diff --git a/examples/nfc/ndefeditor/textrecordeditor.h b/examples/nfc/ndefeditor/textrecordeditor.h
deleted file mode 100644
index 0289ab85..00000000
--- a/examples/nfc/ndefeditor/textrecordeditor.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#ifndef TEXTRECORDEDITOR_H
-#define TEXTRECORDEDITOR_H
-
-#include <QtNfc/qndefnfctextrecord.h>
-
-#include <QtWidgets/QWidget>
-
-QT_BEGIN_NAMESPACE
-namespace Ui {
- class TextRecordEditor;
-}
-QT_END_NAMESPACE
-
-//! [0]
-class TextRecordEditor : public QWidget
-{
- Q_OBJECT
-
-public:
- explicit TextRecordEditor(QWidget *parent = 0);
- ~TextRecordEditor();
-
- void setRecord(const QNdefNfcTextRecord &textRecord);
- QNdefNfcTextRecord record() const;
-
-private:
- Ui::TextRecordEditor *ui;
-};
-//! [0]
-
-#endif // TEXTRECORDEDITOR_H
diff --git a/examples/nfc/ndefeditor/textrecordeditor.ui b/examples/nfc/ndefeditor/textrecordeditor.ui
deleted file mode 100644
index 41950e7d..00000000
--- a/examples/nfc/ndefeditor/textrecordeditor.ui
+++ /dev/null
@@ -1,101 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>TextRecordEditor</class>
- <widget class="QWidget" name="TextRecordEditor">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>344</width>
- <height>115</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="windowTitle">
- <string>Form</string>
- </property>
- <layout class="QFormLayout" name="formLayout">
- <property name="rowWrapPolicy">
- <enum>QFormLayout::WrapLongRows</enum>
- </property>
- <item row="0" column="0" colspan="2">
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>NFC Text Record</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_7">
- <property name="text">
- <string>Text:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="text">
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_6">
- <property name="text">
- <string>Locale:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLineEdit" name="locale">
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Encoding:</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QComboBox" name="encoding">
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <item>
- <property name="text">
- <string>UTF-8</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>UTF-16</string>
- </property>
- </item>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/examples/nfc/ndefeditor/urirecordeditor.cpp b/examples/nfc/ndefeditor/urirecordeditor.cpp
deleted file mode 100644
index 43ed23f6..00000000
--- a/examples/nfc/ndefeditor/urirecordeditor.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#include "urirecordeditor.h"
-#include "ui_urirecordeditor.h"
-
-#include <QtCore/QUrl>
-
-UriRecordEditor::UriRecordEditor(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::UriRecordEditor)
-{
- ui->setupUi(this);
-}
-
-UriRecordEditor::~UriRecordEditor()
-{
- delete ui;
-}
-
-void UriRecordEditor::setRecord(const QNdefNfcUriRecord &uriRecord)
-{
- ui->uri->setText(uriRecord.uri().toString());
-}
-
-QNdefNfcUriRecord UriRecordEditor::record() const
-{
- QNdefNfcUriRecord record;
-
- record.setUri(ui->uri->text());
-
- return record;
-}
diff --git a/examples/nfc/ndefeditor/urirecordeditor.h b/examples/nfc/ndefeditor/urirecordeditor.h
deleted file mode 100644
index 2a2a3736..00000000
--- a/examples/nfc/ndefeditor/urirecordeditor.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#ifndef URIRECORDEDITOR_H
-#define URIRECORDEDITOR_H
-
-#include <QtNfc/qndefnfcurirecord.h>
-
-#include <QtWidgets/QWidget>
-
-QT_BEGIN_NAMESPACE
-namespace Ui {
- class UriRecordEditor;
-}
-QT_END_NAMESPACE
-
-//! [0]
-class UriRecordEditor : public QWidget
-{
- Q_OBJECT
-
-public:
- explicit UriRecordEditor(QWidget *parent = 0);
- ~UriRecordEditor();
-
- void setRecord(const QNdefNfcUriRecord &uriRecord);
- QNdefNfcUriRecord record() const;
-
-private:
- Ui::UriRecordEditor *ui;
-};
-//! [0]
-#endif // URIRECORDEDITOR_H
diff --git a/examples/nfc/ndefeditor/urirecordeditor.ui b/examples/nfc/ndefeditor/urirecordeditor.ui
deleted file mode 100644
index 929c1eb4..00000000
--- a/examples/nfc/ndefeditor/urirecordeditor.ui
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>UriRecordEditor</class>
- <widget class="QWidget" name="UriRecordEditor">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>439</width>
- <height>59</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Form</string>
- </property>
- <layout class="QFormLayout" name="formLayout">
- <item row="0" column="0" colspan="2">
- <widget class="QLabel" name="label_8">
- <property name="text">
- <string>NFC URI Record</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_9">
- <property name="text">
- <string>Uri:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="uri">
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/examples/nfc/nfc.pro b/examples/nfc/nfc.pro
index f76426de..49d54525 100644
--- a/examples/nfc/nfc.pro
+++ b/examples/nfc/nfc.pro
@@ -1,6 +1,7 @@
TEMPLATE = subdirs
qtHaveModule(widgets) {
- SUBDIRS += \
- annotatedurl \
- ndefeditor
+ SUBDIRS += annotatedurl
+}
+qtHaveModule(quickcontrols2) {
+ SUBDIRS += ndefeditor
}