Skip to content
Snippets Groups Projects
Commit 7bc6ddac authored by Burak Hançerli's avatar Burak Hançerli :headphones:
Browse files

QDS-11412 Implement built-in QR code reader

parent ec626d27
No related branches found
No related tags found
1 merge request!28QDS-11412 Implement built-in QR code reader
Pipeline #66038 passed
[submodule "qtquickdesigner-components"]
path = qtquickdesigner-components
path = 3rdparty/qtquickdesigner-components
url = https://git.qt.io/design-studio/kit-dependencies/qt-quickdesigner-components.git
[submodule "emsdk"]
path = emsdk
url = https://github.com/emscripten-core/emsdk.git
[submodule "3rdparty/zxing-cpp"]
path = 3rdparty/zxing-cpp
url = https://github.com/zxing-cpp/zxing-cpp.git
[submodule "3rdparty/qtquickdesigner-components"]
path = 3rdparty/qtquickdesigner-components
url = https://git.qt.io/design-studio/kit-dependencies/qt-quickdesigner-components
Subproject commit 5736952b4b0c8aab4ae56b622ea9a53ae718b60a
Subproject commit c97fc94e0e129feb0c3596371f86d725540322d7
......@@ -19,7 +19,7 @@ find_package(
find_package(
Qt6
COMPONENTS Core Widgets Quick Gui Qml
COMPONENTS Core Widgets Quick Gui Qml Multimedia MultimediaWidgets
REQUIRED
)
......@@ -28,6 +28,9 @@ if(QT_VERSION VERSION_LESS QT_MINIMUM_VERSION)
message(FATAL_ERROR "Minimum supported Qt version: ${QT_MINIMUM_VERSION}")
endif()
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/zxing-cpp)
qt_add_executable(${PROJECT_NAME}
src/importdummy.qml
src/main.cpp
......@@ -35,14 +38,16 @@ qt_add_executable(${PROJECT_NAME}
src/serviceConnector.cpp src/serviceConnector.h
src/projectManager.cpp src/projectManager.h
src/dsConnector.cpp src/dsConnector.h
3rdparty/zxing-cpp/example/ZXingQtReader.h
ui/main.qml
ui/resources.qrc
)
target_link_libraries(${PROJECT_NAME} PRIVATE
Qt6::Core Qt6::Widgets
Qt6::Quick Qt6::Gui
Qt6::Qml Qt6::GuiPrivate
Qt::Core Qt::Widgets
Qt::Quick Qt::Gui
Qt::Qml Qt::GuiPrivate Qt::Multimedia Qt::MultimediaWidgets
ZXing::ZXing
)
set_property(TARGET ${PROJECT_NAME}
......@@ -69,11 +74,13 @@ set_property(TARGET ${PROJECT_NAME} PROPERTY QT_ANDROID_TARGET_SDK_VERSION 34)
qt6_import_qml_plugins(${PROJECT_NAME})
execute_process(COMMAND git describe --always --tags OUTPUT_VARIABLE GIT_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND git -C ${CMAKE_SOURCE_DIR}/qtquickdesigner-components describe --always --tags OUTPUT_VARIABLE QT_QUICK_COMPONENTS_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND git -C ${CMAKE_SOURCE_DIR}/3rdparty/qtquickdesigner-components describe --always --tags OUTPUT_VARIABLE QT_QUICK_COMPONENTS_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND git -C ${CMAKE_SOURCE_DIR}/3rdparty/zxing-cpp describe --always --tags OUTPUT_VARIABLE ZXING-CPP OUTPUT_STRIP_TRAILING_WHITESPACE)
add_definitions( -DGIT_VERSION="${GIT_VERSION}" )
add_definitions( -DQT_QUICK_COMPONENTS_VERSION="${QT_QUICK_COMPONENTS_VERSION}" )
message(STATUS "GIT_VERSION: ${GIT_VERSION}")
message(STATUS "QT_QUICK_COMPONENTS_VERSION: ${QT_QUICK_COMPONENTS_VERSION}")
message(STATUS "PROJECT VERSION: ${GIT_VERSION}")
message(STATUS "QT_VERSION: ${QT_VERSION}")
message(STATUS "QT_QUICK_COMPONENTS_VERSION: ${QT_QUICK_COMPONENTS_VERSION}")
message(STATUS "ZXING-CPP: ${ZXING-CPP}")
......@@ -19,7 +19,9 @@ Qt Design Viewer works with minimum Android 33.
* android: Files needed for Android build system
* src: Backend source files
* ui: UI source files
* qtquickdesigner-components: Required 3rd party QML components
* 3rdparty: Required 3rd party libraries
* qtquickdesigner-components: QML components
* zxing-cpp: QR code decoding/encoding
## Building
......@@ -36,7 +38,7 @@ Build instructions are provided for Linux and macOS hosts. Windows should work a
First build and install QtQuickDesigner Components for Android:
```bash
cd qtquickdesigner-components
pushd 3rdparty/qtquickdesigner-components
cmake \
-S . \
-B build \
......@@ -50,7 +52,7 @@ cmake \
cmake --build build
cmake --install build
cd ..
popd
```
Then build the Qt Design Viewer:
......@@ -71,3 +73,13 @@ cmake --build build
## Usage
Upload the final APK file to your Android device and run. Then follow the instructions within the app.
## 3rd Party Libraries/Components
* [zxing-cpp](https://github.com/zxing-cpp/zxing-cpp.git)
Apache License 2.0
ZXing C++ port for QR code decoding.
* [QtQuickDesigner Components](https://codereview.qt-project.org/gitweb?p=qt-labs%2Fqtquickdesigner-components.git;a=summary)
GNU GENERAL PUBLIC LICENSE
QtQuickDesigner Components is a collection of QML components for Qt Quick Designer.
<?xml version="1.0"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.qt.qtdesignviewer"
android:installLocation="auto" android:versionCode="21" android:versionName="1.2">
android:installLocation="auto" android:versionCode="22" android:versionName="1.2">
<!-- %%INSERT_PERMISSIONS -->
<!-- %%INSERT_FEATURES -->
<supports-screens android:anyDensity="true" android:largeScreens="true"
......@@ -9,6 +9,7 @@
android:extractNativeLibs="true" android:hardwareAccelerated="true"
android:label="Qt UI Viewer" android:requestLegacyExternalStorage="true"
android:allowNativeHeapPointerTagging="false" android:icon="@mipmap/app_icon">
<profileable android:shell="true" android:enabled="true" />
<activity android:name="org.qtproject.qt.android.bindings.QtActivity"
android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
android:label="Qt UI Viewer" android:launchMode="singleTask"
......
variables:
QDS_CI_QT_VERSION:
value: "652"
value: "661"
options:
- "643"
- "652"
- "661"
description: "Qt version for build"
QDS_CI_ARTIFACTS_PATH: "${CI_PROJECT_DIR}/artifacts"
DEBIAN_FRONTEND: non-interactive
......
......@@ -20,7 +20,6 @@ build-android-multiarch:
QDS_BUILD_PATH: "${CI_PROJECT_DIR}/outdir/build"
QDS_CI_JOB_ARTIFACTS_PATH: ${QDS_CI_ARTIFACTS_PATH}/${QDS_CI_JOB_TARGET_PLATFORM}/${QDS_CI_JOB_TARGET_ARCH}
QDS_CI_JOB_TARGET_PLATFORM: "android"
QDS_CI_QT_VERSION: "652"
image: "git.qt.io:4567/design-studio/maintenance/docker-images/${QDS_CI_JOB_TARGET_PLATFORM}:${QDS_CI_QT_VERSION}-${QDS_CI_JOB_TARGET_PLATFORM}-${QDS_CI_JOB_TARGET_ARCH}"
artifacts:
name: design-viewer-${CI_JOB_ID}-qt${QDS_CI_QT_VERSION}-${QDS_CI_JOB_TARGET_PLATFORM}-${QDS_CI_JOB_TARGET_ARCH}
......@@ -31,9 +30,9 @@ build-android-multiarch:
- if: $QDS_CI_QT_VERSION_ANDROID != "none"
script:
- mkdir -p ${QDS_CI_JOB_ARTIFACTS_PATH}
- cd qtquickdesigner-components
- ls -l /opt/openssl/ssl_3/
- ls -l ${QDS_CI_JOB_OPENSSL_PATH}
- pushd 3rdparty/qtquickdesigner-components
- |
cmake \
-S . \
......@@ -47,7 +46,7 @@ build-android-multiarch:
-DANDROID_OPENSSL_PATH=${QDS_CI_JOB_OPENSSL_PATH}
- cmake --build .
- cmake --install .
- cd ..
- popd
- |
cmake \
-S . \
......
Subproject commit 55dfd50975935efbe67ea8cdb77ac01e4640db88
......@@ -26,13 +26,19 @@
#include "backend.h"
#include "qapplication.h"
#include <QCameraDevice>
#include <QDesktopServices>
#include <QFileInfo>
#include <QJsonArray>
#include <QJsonObject>
#include <QMediaDevices>
#include <QSettings>
#include <QSslSocket>
#include <QVideoSink>
#include "../3rdparty/zxing-cpp/example/ZXingQtReader.h"
using namespace ZXingQt;
Backend::Backend(QObject *parent)
: QObject(parent)
......@@ -104,6 +110,50 @@ void Backend::updateInBackground(const bool &enabled)
}
}
void Backend::scanQrCode()
{
m_captureSession.reset(new QMediaCaptureSession(this));
m_captureSession->setCamera(new QCamera(this));
m_captureSession->setVideoOutput(new CustomVideoWidget);
m_captureSession->camera()->setFocusMode(QCamera::FocusModeAuto);
CustomVideoWidget *videoWidget = qobject_cast<CustomVideoWidget *>(
m_captureSession->videoOutput());
connect(m_captureSession->videoSink(),
&QVideoSink::videoFrameChanged,
this,
[&](const QVideoFrame &frame) {
static int i = 0;
if (i++ < 30) {
return;
}
i = 0;
auto results = ReadBarcodes(frame.toImage());
for (auto &result : results) {
qDebug() << "Text: " << result.text();
qDebug() << "Format: " << result.format();
qDebug() << "Content:" << result.contentType();
parseDesignViewerUrl(result.text());
qobject_cast<CustomVideoWidget *>(m_captureSession->videoOutput())->close();
}
});
connect(videoWidget, &CustomVideoWidget::closed, this, [&] {
qDebug() << "Video widget closed. Clearing capture session";
m_captureSession->camera()->stop();
m_captureSession->camera()->deleteLater();
m_captureSession->videoOutput()->deleteLater();
m_captureSession.clear();
});
videoWidget->show();
m_captureSession->camera()->start();
}
void Backend::cacheDemoProjects(const bool &enabled)
{
QSettings().setValue("system/cacheDemoProjects", enabled);
......
......@@ -26,12 +26,35 @@
#ifndef DV_ANDROID_H
#define DV_ANDROID_H
#include <QCamera>
#include <QImageCapture>
#include <QMediaCaptureSession>
#include <QThread>
#include <QVideoWidget>
#include <QWidget>
#include "dsConnector.h"
#include "projectManager.h"
#include "serviceConnector.h"
#include <QLabel>
#include <QVBoxLayout>
class CustomVideoWidget : public QVideoWidget
{
Q_OBJECT
public:
explicit CustomVideoWidget(QWidget *parent = nullptr)
: QVideoWidget(parent)
{}
~CustomVideoWidget() override {}
void closeEvent(QCloseEvent *event) override { emit closed(); }
signals:
void closed();
};
class Backend : public QObject
{
Q_OBJECT
......@@ -64,6 +87,7 @@ private:
QThread m_dsConnectorThread;
QTimer m_backgroundTimer;
QSharedPointer<QMediaCaptureSession> m_captureSession;
// member functions
void updateUserProjectList();
......@@ -84,6 +108,8 @@ signals:
void urlUpdated(QString);
public slots:
void scanQrCode();
void runOnlineProject(const QString &url);
void runUserProject(const QString &projectName);
void runDemoProject(const QString &projectName);
......
......@@ -24,8 +24,10 @@
****************************************************************************/
#include <android/log.h>
#include <QApplication>
#include <QMessageBox>
#include <QPermission>
#include <QQmlContext>
#include "backend.h"
......@@ -83,6 +85,25 @@ int main(int argc, char *argv[])
QQuickView view;
backend = new Backend();
// request permissions
QCameraPermission permission;
switch (app.checkPermission(permission)) {
case Qt::PermissionStatus::Granted:
break;
case Qt::PermissionStatus::Undetermined:
case Qt::PermissionStatus::Denied:
app.requestPermission(permission, [](const QPermission &permission) {
if (permission.status() == Qt::PermissionStatus::Denied) {
QMessageBox msgBox{QMessageBox::Critical,
"Critical:",
"Camera permission denied",
QMessageBox::Ok};
msgBox.exec();
}
});
break;
}
view.engine()->rootContext()->setContextProperty("backend", backend);
view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
view.setResizeMode(QQuickView::SizeRootObjectToView);
......
......@@ -40,7 +40,11 @@
#include <QStandardPaths>
#include <QTemporaryDir>
#include <QTemporaryFile>
#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
#include <QtCore/private/qzipreader_p.h>
#else
#include <QtGui/private/qzipreader_p.h>
#endif
ProjectManager::ProjectManager(QObject *parent)
: QObject(parent)
......
......@@ -46,7 +46,21 @@ Item {
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
Button {
id: scanQrCode
text: qsTr("Scan QR Code")
onClicked: backend.scanQrCode()
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
}
Item {
id: item4
Layout.preferredWidth: 10
Layout.preferredHeight: 10
Layout.fillWidth: true
Layout.fillHeight: true
}
ColumnLayout {
id: column2
Layout.fillWidth: true
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment