From 7c1c178d37e84c110c0e6f65e914e017b7b006cb Mon Sep 17 00:00:00 2001 From: Igor Sirotin Date: Wed, 8 Mar 2023 05:08:38 +1300 Subject: [PATCH] QR code scanner (QML component) (#9464) Co-authored-by: Richard Ramos --- .gitmodules | 3 + Info.dev.plist | 2 + Info.plist | 2 + Makefile | 14 +- build-linux.sh | 2 +- ci/Dockerfile | 4 +- ci/Jenkinsfile.linux | 2 +- ci/Jenkinsfile.tests-nim | 2 +- docker-linux-app-image.sh | 2 +- scripts/ubuntu_build_setup.sh | 2 +- ui/StatusQ/CMakeLists.txt | 6 + ui/StatusQ/sandbox/CMakeLists.txt | 3 +- ui/StatusQ/sandbox/demoapp/data/Models.qml | 11 ++ ui/StatusQ/sandbox/main.qml | 50 +++++ ui/StatusQ/sandbox/sandboxapp.cpp | 6 +- ui/StatusQ/sanity_checker/CMakeLists.txt | 3 +- ui/StatusQ/sanity_checker/main.cpp | 3 + .../Components/StatusQrCodeScanner.qml | 182 ++++++++++++++++++ ui/StatusQ/src/StatusQ/Components/qmldir | 1 + ui/StatusQ/src/statusq.qrc | 1 + ui/StatusQ/vendor/qzxing | 1 + vendor/DOtherSide/CMakeLists.txt | 1 + vendor/DOtherSide/lib/CMakeLists.txt | 4 +- vendor/DOtherSide/lib/src/DOtherSide.cpp | 2 + 24 files changed, 293 insertions(+), 16 deletions(-) create mode 100644 ui/StatusQ/src/StatusQ/Components/StatusQrCodeScanner.qml create mode 160000 ui/StatusQ/vendor/qzxing diff --git a/.gitmodules b/.gitmodules index 0e3cbf505..167018770 100644 --- a/.gitmodules +++ b/.gitmodules @@ -116,3 +116,6 @@ [submodule "vendor/nim-taskpools"] path = vendor/nim-taskpools url = https://github.com/status-im/nim-taskpools.git +[submodule "ui/StatusQ/vendor/qzxing"] + path = ui/StatusQ/vendor/qzxing + url = https://github.com/status-im/qzxing.git diff --git a/Info.dev.plist b/Info.dev.plist index ebf354ef4..2665c50c6 100644 --- a/Info.dev.plist +++ b/Info.dev.plist @@ -37,5 +37,7 @@ 0 NSHighResolutionCapable True + NSCameraUsageDescription + Scan QR codes diff --git a/Info.plist b/Info.plist index bde2d54e6..194e43a3a 100644 --- a/Info.plist +++ b/Info.plist @@ -37,5 +37,7 @@ 0 NSHighResolutionCapable True + NSCameraUsageDescription + Scan QR codes diff --git a/Makefile b/Makefile index fa7856354..473c99f6e 100644 --- a/Makefile +++ b/Makefile @@ -149,7 +149,7 @@ endif MONITORING ?= false ifneq ($(MONITORING), false) - DOTHERSIDE_CMAKE_PARAMS := ${DOTHERSIDE_CMAKE_PARAMS} -DMONITORING:BOOL=ON -DMONITORING_QML_ENTRY_POINT:STRING="/../monitoring/Main.qml" + DOTHERSIDE_CMAKE_PARAMS += -DMONITORING:BOOL=ON -DMONITORING_QML_ENTRY_POINT:STRING="/../monitoring/Main.qml" endif @@ -175,18 +175,23 @@ ifneq ($(detected_OS),Windows) NIM_PARAMS += --passL:"-L$(QT5_LIBDIR)" endif endif + # We manually link QZXing to Nim application, + # because static libraries are not compiled into other static libraries (DOtherSide). + QZXING := vendor/DOtherSide/build/qzxing/libqzxing.a DOTHERSIDE := vendor/DOtherSide/build/lib/libDOtherSideStatic.a DOTHERSIDE_CMAKE_PARAMS += -DENABLE_DYNAMIC_LIBS=OFF -DENABLE_STATIC_LIBS=ON # order matters here, due to "-Wl,-as-needed" - NIM_PARAMS += --passL:"$(DOTHERSIDE)" --passL:"$(shell PKG_CONFIG_PATH="$(QT5_PCFILEDIR)" pkg-config --libs Qt5Core Qt5Qml Qt5Gui Qt5Quick Qt5QuickControls2 Qt5Widgets Qt5Svg Qt5Multimedia)" + NIM_PARAMS += --passL:"$(DOTHERSIDE)" --passL:"$(QZXING)" --passL:"$(shell PKG_CONFIG_PATH="$(QT5_PCFILEDIR)" pkg-config --libs Qt5Core Qt5Qml Qt5Gui Qt5Quick Qt5QuickControls2 Qt5Widgets Qt5Svg Qt5Multimedia)" else ifneq ($(QML_DEBUG), false) + QZXING := vendor/DOtherSide/build/qzxing/Debug/qzxing.lib DOTHERSIDE := vendor/DOtherSide/build/lib/Debug/DOtherSide.dll else + QZXING := vendor/DOtherSide/build/qzxing/Release/qzxing.lib DOTHERSIDE := vendor/DOtherSide/build/lib/Release/DOtherSide.dll endif DOTHERSIDE_CMAKE_PARAMS += -T"v141" -A x64 -DENABLE_DYNAMIC_LIBS=ON -DENABLE_STATIC_LIBS=OFF - NIM_PARAMS += -L:$(DOTHERSIDE) + NIM_PARAMS += -L:$(DOTHERSIDE) -L:$(QZXING) NIM_EXTRA_PARAMS := --passL:"-lsetupapi -lhid" endif @@ -238,6 +243,9 @@ $(DOTHERSIDE): | deps cmake $(DOTHERSIDE_CMAKE_PARAMS)\ -DENABLE_DOCS=OFF \ -DENABLE_TESTS=OFF \ + -DQZXING_USE_QML=ON \ + -DQZXING_MULTIMEDIA=ON \ + -DQZXING_USE_DECODER_QR_CODE=ON \ .. $(HANDLE_OUTPUT) && \ $(DOTHERSIDE_BUILD_CMD) diff --git a/build-linux.sh b/build-linux.sh index e2c448299..5baa546e4 100755 --- a/build-linux.sh +++ b/build-linux.sh @@ -13,5 +13,5 @@ docker run -it --rm \ -u jenkins:$(getent group $(whoami) | cut -d: -f3) \ -v "${PWD}:/status-desktop" \ -w /status-desktop \ - statusteam/nim-status-client-build:1.2.0-qt5.15.2 \ + statusteam/nim-status-client-build:1.2.1-qt5.15.2 \ ./docker-linux-app-image.sh diff --git a/ci/Dockerfile b/ci/Dockerfile index 59a355f0b..fd11db918 100644 --- a/ci/Dockerfile +++ b/ci/Dockerfile @@ -40,10 +40,10 @@ RUN apt update -yq && apt install -yq software-properties-common \ && add-apt-repository -y ppa:git-core/ppa \ && add-apt-repository -y ppa:ubuntu-toolchain-r/test \ && apt update -yq && apt full-upgrade -yq && apt install -yq --no-install-recommends --fix-missing \ - gnupg2 openssh-client ca-certificates locales sudo jq curl wget fuse s3cmdfile llvm tk-dev xz-utils \ + gnupg2 openssh-client ca-certificates locales sudo jq curl wget fuse s3cmd file llvm tk-dev xz-utils \ git make build-essential pkg-config cmake extra-cmake-modules gcc-9 g++-9 \ libgl1-mesa-dev libsm6 libice6 libfontconfig1 libdbus-1-3 libssl-dev libz-dev \ - zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \ + zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev unixodbc-dev libpq-dev \ libncurses5-dev libncursesw5-dev libpcsclite-dev libpcre3-dev libnss3 \ gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \ gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-alsa libpulse-mainloop-glib0 \ diff --git a/ci/Jenkinsfile.linux b/ci/Jenkinsfile.linux index ab6633b38..7a71a7374 100644 --- a/ci/Jenkinsfile.linux +++ b/ci/Jenkinsfile.linux @@ -7,7 +7,7 @@ pipeline { agent { docker { label 'linux' - image 'statusteam/nim-status-client-build:1.2.0-qt5.15.2' + image 'statusteam/nim-status-client-build:1.2.1-qt5.15.2' /* allows jenkins use cat and mounts '/dev/fuse' for linuxdeployqt */ args '--entrypoint="" --cap-add SYS_ADMIN --security-opt apparmor:unconfined --device /dev/fuse' } diff --git a/ci/Jenkinsfile.tests-nim b/ci/Jenkinsfile.tests-nim index efe4a8e7c..cbf304ece 100644 --- a/ci/Jenkinsfile.tests-nim +++ b/ci/Jenkinsfile.tests-nim @@ -7,7 +7,7 @@ pipeline { agent { docker { label 'linux' - image 'statusteam/nim-status-client-build:1.2.0-qt5.15.2' + image 'statusteam/nim-status-client-build:1.2.1-qt5.15.2' } } diff --git a/docker-linux-app-image.sh b/docker-linux-app-image.sh index 4c2b37bf0..489d29eb0 100755 --- a/docker-linux-app-image.sh +++ b/docker-linux-app-image.sh @@ -4,7 +4,7 @@ cp -R . ~/status-desktop cd ~/status-desktop -git clean -dfx && rm -rf vendor/* && make -j4 V=1 update +git clean -dfx && rm -rf vendor/* && git checkout vendor/DOtherSide && make -j4 V=1 update make V=1 pkg # Make AppImage build accessible to the docker host diff --git a/scripts/ubuntu_build_setup.sh b/scripts/ubuntu_build_setup.sh index 78dc76fb0..df6ee232e 100755 --- a/scripts/ubuntu_build_setup.sh +++ b/scripts/ubuntu_build_setup.sh @@ -18,7 +18,7 @@ function check_version { function install_build_dependencies { echo "Install build dependencies" apt update - apt install -yq git build-essential pkg-config mesa-common-dev \ + apt install -yq git build-essential pkg-config mesa-common-dev unixodbc-dev libpq-dev \ libglu1-mesa-dev wget libpcsclite-dev libpcre3-dev libssl-dev libpulse-mainloop-glib0 \ libxkbcommon-x11-dev extra-cmake-modules cmake } diff --git a/ui/StatusQ/CMakeLists.txt b/ui/StatusQ/CMakeLists.txt index 58b1d8d14..502efa9e5 100644 --- a/ui/StatusQ/CMakeLists.txt +++ b/ui/StatusQ/CMakeLists.txt @@ -13,12 +13,18 @@ set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(QZXING_USE_QML ON) +set(QZXING_MULTIMEDIA ON) +set(QZXING_USE_DECODER_QR_CODE ON) + # https://doc.qt.io/qtcreator/creator-qml-modules-with-plugins.html#importing-qml-modules set(QML_IMPORT_PATH ${CMAKE_SOURCE_DIR}/src;${QML_IMPORT_PATH} CACHE STRING "") + add_subdirectory(vendor/SortFilterProxyModel) +add_subdirectory(vendor/qzxing/src) add_subdirectory(sandbox) add_subdirectory(sanity_checker) add_subdirectory(tests) diff --git a/ui/StatusQ/sandbox/CMakeLists.txt b/ui/StatusQ/sandbox/CMakeLists.txt index 26039c608..cdbcb9aa2 100644 --- a/ui/StatusQ/sandbox/CMakeLists.txt +++ b/ui/StatusQ/sandbox/CMakeLists.txt @@ -32,7 +32,8 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE SRC_DIR="${CMAKE_CURRENT_LIST_DIR}") target_link_libraries( ${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Quick Qt5::QuickControls2 - SortFilterProxyModel) + SortFilterProxyModel + qzxing) if (APPLE) find_library(AppKit AppKit) diff --git a/ui/StatusQ/sandbox/demoapp/data/Models.qml b/ui/StatusQ/sandbox/demoapp/data/Models.qml index 28dcce04c..ffd199132 100644 --- a/ui/StatusQ/sandbox/demoapp/data/Models.qml +++ b/ui/StatusQ/sandbox/demoapp/data/Models.qml @@ -1198,6 +1198,17 @@ QtObject { hasNotification: false notificationsCount: 0 } + ListElement { + sectionId: "demoApp" + sectionType: 103 + name: "QR Scanner" + active: false + image: "" + icon: "qr-scan" + color: "" + hasNotification: false + notificationsCount: 0 + } } property ListModel demoAppSectionsModel: ListModel { diff --git a/ui/StatusQ/sandbox/main.qml b/ui/StatusQ/sandbox/main.qml index 8e2a58ccb..ea8c478c1 100644 --- a/ui/StatusQ/sandbox/main.qml +++ b/ui/StatusQ/sandbox/main.qml @@ -5,6 +5,7 @@ import QtGraphicalEffects 1.13 import QtQuick.Layouts 1.14 import Qt.labs.settings 1.0 import QtQml.Models 2.14 +import QtMultimedia 5.14 import StatusQ 0.1 @@ -49,6 +50,7 @@ StatusWindow { readonly property int apiDocumentation: 100 readonly property int examples: 101 readonly property int demoApp: 102 + readonly property int qrScanner: 103 } function setActiveItem(sectionId) { @@ -97,6 +99,10 @@ StatusWindow { { stackView.push(demoAppCmp) } + else if (model.sectionType === appSectionType.qrScanner) + { + stackView.push(qrScannerComponent) + } rootWindow.setActiveItem(model.sectionId) } } @@ -537,6 +543,50 @@ StatusWindow { } } + Component { + id: qrScannerComponent + + Rectangle { + anchors.fill: parent + color: Theme.palette.baseColor3 + + ColumnLayout { + anchors.fill: parent + anchors.margins: 20 + spacing: 10 + + StatusQrCodeScanner { + id: qrScanner + Layout.fillWidth: true + Layout.preferredHeight: width / sourceRatio + } + + RowLayout { + Layout.fillWidth: true + spacing: 10 + + StatusBaseText { + text: qsTr("Last tag: ") + } + + StatusInput { + id: lastTagText + Layout.fillWidth: true + input.enabled: false + text: qrScanner.lastTag + input.rightPadding: 10 + } + + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + } + } + } + StatusMacTrafficLights { anchors.left: parent.left anchors.top: parent.top diff --git a/ui/StatusQ/sandbox/sandboxapp.cpp b/ui/StatusQ/sandbox/sandboxapp.cpp index 85b9a0a68..4a5159f75 100644 --- a/ui/StatusQ/sandbox/sandboxapp.cpp +++ b/ui/StatusQ/sandbox/sandboxapp.cpp @@ -6,15 +6,17 @@ #include #include "StatusQ/typesregistration.h" +#include SandboxApp::SandboxApp(int &argc, char **argv) : QGuiApplication(argc, argv) { + QZXing::registerQMLTypes(); + #ifdef QT_DEBUG - connect(&m_watcher, &QFileSystemWatcher::directoryChanged, [this](const QString&) { + connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, [this](const QString&) { restartEngine(); }); - #endif } diff --git a/ui/StatusQ/sanity_checker/CMakeLists.txt b/ui/StatusQ/sanity_checker/CMakeLists.txt index da61e8019..f3b8bbde4 100644 --- a/ui/StatusQ/sanity_checker/CMakeLists.txt +++ b/ui/StatusQ/sanity_checker/CMakeLists.txt @@ -23,7 +23,8 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${STATUSQ_DIR}/include) target_link_libraries( ${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Quick Qt5::QuickControls2 - SortFilterProxyModel) + SortFilterProxyModel + qzxing) if (APPLE) find_library(AppKit AppKit) diff --git a/ui/StatusQ/sanity_checker/main.cpp b/ui/StatusQ/sanity_checker/main.cpp index 9c970b8b7..0db40aab3 100644 --- a/ui/StatusQ/sanity_checker/main.cpp +++ b/ui/StatusQ/sanity_checker/main.cpp @@ -5,6 +5,7 @@ #include #include "StatusQ/typesregistration.h" +#include int main(int argc, char *argv[]) { @@ -16,6 +17,8 @@ int main(int argc, char *argv[]) engine.addImportPath(QStringLiteral(":/")); + QZXing::registerQMLTypes(); + QDirIterator it(":", QDirIterator::Subdirectories); bool errorsFound = false; diff --git a/ui/StatusQ/src/StatusQ/Components/StatusQrCodeScanner.qml b/ui/StatusQ/src/StatusQ/Components/StatusQrCodeScanner.qml new file mode 100644 index 000000000..4133c97a5 --- /dev/null +++ b/ui/StatusQ/src/StatusQ/Components/StatusQrCodeScanner.qml @@ -0,0 +1,182 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import QtMultimedia 5.15 +import QtGraphicalEffects 1.0 + +import StatusQ.Controls 0.1 +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 + +import QZXing 3.3 + +Item { + id: root + + readonly property alias camera: camera + + readonly property size sourceSize: Qt.size(videoOutput.sourceRect.width, videoOutput.sourceRect.height) + readonly property size contentSize: Qt.size(videoOutput.contentRect.width, videoOutput.contentRect.height) + readonly property real sourceRatio: videoOutput.sourceRect.width / videoOutput.sourceRect.height + + property int failsCount: 0 + property int tagsCount: 0 + property int decodeTime: 0 + + property string lastTag + + implicitWidth: sourceSize.width + implicitHeight: sourceSize.height + + signal tagFound(string tag) + + QtObject { + id: d + + readonly property int radius: 16 + } + + Camera { + id: camera + captureMode: Camera.CaptureVideo + focus { + focusMode: CameraFocus.FocusContinuous + focusPointMode: CameraFocus.FocusPointAuto + } + } + + Rectangle { + anchors.fill: parent + color: Theme.palette.baseColor4 + radius: d.radius + } + + Item { + anchors.fill: parent + implicitWidth: videoOutput.contentRect.width + implicitHeight: videoOutput.contentRect.height + visible: camera.availability === Camera.Available + + VideoOutput { + id: videoOutput + anchors.fill: parent + visible: false + source: camera + filters: [ qzxingFilter ] + fillMode: VideoOutput.PreserveAspectFit + } + + Rectangle { + id: mask + anchors.fill: parent + radius: 16 + visible: false + color: "black" + } + + OpacityMask { + anchors.fill: parent + source: videoOutput + maskSource: mask + } + + QZXingFilter { + id: qzxingFilter + orientation: videoOutput.orientation + captureRect: { + videoOutput.contentRect; videoOutput.sourceRect; // bindings + const normalizedRectangle = Qt.rect(0, 0, 1, 1) + const rectangle = videoOutput.mapNormalizedRectToItem(normalizedRectangle) + return videoOutput.mapRectToSource(rectangle); + } + + decoder { + enabledDecoders: QZXing.DecoderFormat_QR_CODE + tryHarder: true + onTagFound: { + root.lastTag = tag + root.tagFound(tag) + } + } + + onDecodingFinished: { + if (succeeded) + ++root.tagsCount + else + ++root.failsCount + root.decodeTime = decodeTime + } + } + } + + // TODO: Implement camera selector + // For me it works once. The first switch between 2 cameras is ok. + // The second switch doesn't work and behaves different with 2 approaches: + // With standard `ComboBox` it throws an exception. + // Width `StatusComboBox` it just kinda unbinds from the Camera. + // + // ComboBox { + // id: cameraComboBox + + // anchors { + // right: parent.right + // bottom: parent.bottom + // margins: 10 + // } + + // width: implicitWidth + // opacity: 0.7 + // model: QtMultimedia.availableCameras + // textRole: "displayName" + // valueRole: "deviceId" + // onCurrentValueChanged: { + // camera.deviceId = currentValue + // } + // } + + // StatusComboBox { + // id: cameraComboBox + // anchors { + // right: parent.right + // bottom: parent.bottom + // margins: 10 + // } + + // width: implicitWidth + // opacity: 0.7 + // model: QtMultimedia.availableCameras + // control.textRole: "displayName" + // control.valueRole: "deviceId" + // onCurrentValueChanged: { + // console.log("setting deviceId to", currentValue) + // camera.deviceId = currentValue + // } + // } + + ColumnLayout { + anchors.verticalCenter: parent.verticalCenter + width: parent.width + + spacing: 10 + + StatusBaseText { + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: Theme.palette.dangerColor1 + visible: camera.availability !== Camera.Available + text: qsTr("Camera is not available") + } + + StatusBaseText { + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: Theme.palette.directColor5 + visible: camera.errorCode !== Camera.NoError + text: "Error comes here" // camera.errorString + } + } +} + diff --git a/ui/StatusQ/src/StatusQ/Components/qmldir b/ui/StatusQ/src/StatusQ/Components/qmldir index 622deda99..a4ccadaa7 100644 --- a/ui/StatusQ/src/StatusQ/Components/qmldir +++ b/ui/StatusQ/src/StatusQ/Components/qmldir @@ -49,3 +49,4 @@ StatusChart 0.1 StatusChart.qml StatusChartPanel 0.1 StatusChartPanel.qml StatusStepper 0.1 StatusStepper.qml LoadingComponent 0.1 LoadingComponent.qml +StatusQrCodeScanner 0.1 StatusQrCodeScanner.qml diff --git a/ui/StatusQ/src/statusq.qrc b/ui/StatusQ/src/statusq.qrc index 12e767cce..e32805d04 100644 --- a/ui/StatusQ/src/statusq.qrc +++ b/ui/StatusQ/src/statusq.qrc @@ -196,5 +196,6 @@ StatusQ/Core/Utils/ModelUtils.qml StatusQ/Core/Utils/ModelsComparator.qml StatusQ/Core/Utils/ModelChangeTracker.qml + StatusQ/Components/StatusQrCodeScanner.qml diff --git a/ui/StatusQ/vendor/qzxing b/ui/StatusQ/vendor/qzxing new file mode 160000 index 000000000..80bb1d219 --- /dev/null +++ b/ui/StatusQ/vendor/qzxing @@ -0,0 +1 @@ +Subproject commit 80bb1d21903881e4061a41739d413a296ceb3b49 diff --git a/vendor/DOtherSide/CMakeLists.txt b/vendor/DOtherSide/CMakeLists.txt index d4b174098..5f22c7e8e 100644 --- a/vendor/DOtherSide/CMakeLists.txt +++ b/vendor/DOtherSide/CMakeLists.txt @@ -28,6 +28,7 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) endif() endif() +add_subdirectory(../../ui/StatusQ/vendor/qzxing/src qzxing) add_subdirectory(../../ui/StatusQ/vendor/SortFilterProxyModel SortFilterProxyModel) add_subdirectory(lib) diff --git a/vendor/DOtherSide/lib/CMakeLists.txt b/vendor/DOtherSide/lib/CMakeLists.txt index 6c96a280c..487a8120f 100644 --- a/vendor/DOtherSide/lib/CMakeLists.txt +++ b/vendor/DOtherSide/lib/CMakeLists.txt @@ -38,7 +38,7 @@ macro(add_target name type) target_include_directories(${name} PUBLIC include include/Qt ${STATUSQ_DIR}/include) - target_link_libraries(${name} PRIVATE Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Qml Qt5::Quick Qt5::Network Qt5::Multimedia SortFilterProxyModel) + target_link_libraries(${name} PRIVATE Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Qml Qt5::Quick Qt5::Network Qt5::Multimedia SortFilterProxyModel qzxing) target_compile_definitions(${name} PRIVATE $<$:QT_QML_DEBUG>) if(DEFINED QML_DEBUG_PORT) @@ -53,7 +53,7 @@ macro(add_target name type) endif() # for DOtherSide.pc - set(PC_REQUIRES "Qt5Core, Qt5Gui, Qt5Widgets, Qt5Qml, Qt5Quick, Qt5Network, Qt5DBus, Qt5Multimedia, SortFilterProxyModel") + set(PC_REQUIRES "Qt5Core, Qt5Gui, Qt5Widgets, Qt5Qml, Qt5Quick, Qt5Network, Qt5DBus, Qt5Multimedia, SortFilterProxyModel, qzxing") if (${Qt5QuickControls2_FOUND}) target_link_libraries(${name} PRIVATE Qt5::QuickControls2) set(PC_REQUIRES "${PC_REQUIRES}, Qt5QuickControls2") diff --git a/vendor/DOtherSide/lib/src/DOtherSide.cpp b/vendor/DOtherSide/lib/src/DOtherSide.cpp index e149cbca9..c103348e6 100644 --- a/vendor/DOtherSide/lib/src/DOtherSide.cpp +++ b/vendor/DOtherSide/lib/src/DOtherSide.cpp @@ -85,6 +85,7 @@ #endif #include +#include namespace { @@ -103,6 +104,7 @@ void register_meta_types() #endif qqsfpm::registerTypes(); + QZXing::registerQMLTypes(); } }