QR code scanner (QML component) (#9464)
Co-authored-by: Richard Ramos <info@richardramos.me>
This commit is contained in:
parent
eed98809d1
commit
7c1c178d37
|
@ -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
|
||||
|
|
|
@ -37,5 +37,7 @@
|
|||
<integer>0</integer>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Scan QR codes</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -37,5 +37,7 @@
|
|||
<integer>0</integer>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Scan QR codes</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
14
Makefile
14
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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -43,7 +43,7 @@ RUN apt update -yq && apt install -yq software-properties-common \
|
|||
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 \
|
||||
|
|
|
@ -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'
|
||||
}
|
||||
|
|
|
@ -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'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -6,15 +6,17 @@
|
|||
#include <QDirIterator>
|
||||
|
||||
#include "StatusQ/typesregistration.h"
|
||||
#include <QZXing.h>
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <QQmlEngine>
|
||||
|
||||
#include "StatusQ/typesregistration.h"
|
||||
#include <QZXing>
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
@ -196,5 +196,6 @@
|
|||
<file>StatusQ/Core/Utils/ModelUtils.qml</file>
|
||||
<file>StatusQ/Core/Utils/ModelsComparator.qml</file>
|
||||
<file>StatusQ/Core/Utils/ModelChangeTracker.qml</file>
|
||||
<file>StatusQ/Components/StatusQrCodeScanner.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 80bb1d21903881e4061a41739d413a296ceb3b49
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 $<$<CONFIG:Debug>: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")
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
#endif
|
||||
|
||||
#include <qqmlsortfilterproxymodeltypes.h>
|
||||
#include <QZXing.h>
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -103,6 +104,7 @@ void register_meta_types()
|
|||
#endif
|
||||
|
||||
qqsfpm::registerTypes();
|
||||
QZXing::registerQMLTypes();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue