Skip to content

Commit

Permalink
QR code input (#3009)
Browse files Browse the repository at this point in the history
* Added QR Code Input

* QR code logic finished

* Added fake classes to use QR camera component in Gallery app

* Use ApplicationWindow.window.width instead of window.width

* Applied review comments

* C++ formatting
  • Loading branch information
iiLubos authored Jan 17, 2024
1 parent 1a91423 commit 5da384e
Show file tree
Hide file tree
Showing 11 changed files with 292 additions and 11 deletions.
6 changes: 3 additions & 3 deletions app/position/tracking/androidtrackingbackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ AndroidTrackingBackend::~AndroidTrackingBackend()
QAndroidIntent serviceIntent( activity.object(), "uk/co/lutraconsulting/PositionTrackingService" );

activity.callMethod<jboolean>(
"stopService",
"(Landroid/content/Intent;)Z",
serviceIntent.handle().object() );
"stopService",
"(Landroid/content/Intent;)Z",
serviceIntent.handle().object() );

if ( mTrackingFile.isOpen() )
{
Expand Down
8 changes: 4 additions & 4 deletions app/position/tracking/androidtrackingbroadcast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ bool AndroidTrackingBroadcast::registerBroadcastPrivate()
javaenv->DeleteLocalRef( objectClass );

mBroadcastReceiver.callMethod<void>(
"registerBroadcastReceiver",
"(Landroid/content/Context;)V",
QNativeInterface::QAndroidApplication::context()
);
"registerBroadcastReceiver",
"(Landroid/content/Context;)V",
QNativeInterface::QAndroidApplication::context()
);

mBroadcastIsRegistered = true;

Expand Down
134 changes: 134 additions & 0 deletions app/qml/components/MMCodeScanner.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

import QtQuick
import QtQuick.Controls
import QtMultimedia
import lc 1.0 as InputClass

Drawer {
id: root

signal scanFinished( var data )

width: ApplicationWindow.window.width
height: ApplicationWindow.window.height + 40 * __dp
edge: Qt.BottomEdge
dim: true
interactive: false
dragMargin: 0
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside

CaptureSession {
id: captureSession

camera: Camera {
id: camera
active: true
focusMode: Camera.FocusModeAutoNear
}
videoOutput: videoOutput
}

VideoOutput {
id: videoOutput

anchors.fill: parent
fillMode: VideoOutput.PreserveAspectCrop
}

InputClass.QrCodeDecoder {
id: qrcodeScanner

videoSink: videoOutput.videoSink

onCodeScanned: function( codeData ) {
root.unload()
root.scanFinished( codeData )
}
}

Canvas {
id: canvas

anchors.fill: parent
opacity: 0.8

onPaint: {
var ctx = getContext("2d");
let w = parent.width
let h = parent.height
ctx.fillStyle = __style.nightColor
ctx.fillRect(0, 0, parent.width, parent.height);
ctx.fill();
if(parent.width < parent.height)
ctx.clearRect(w / 4, h / 2 - w / 4, w / 2, w / 2)
else
ctx.clearRect(w / 2 - h / 4, h / 4, h / 2, h / 2)
}
}

Item {
width: parent.width
height: (parent.width < parent.height) ? parent.height / 2 - parent.width / 4 : parent.height / 4
anchors.horizontalCenter: parent.horizontalCenter

Column {
id: textColumn

width: parent.width - 40 * __dp
anchors.centerIn: parent
spacing: 10 * __dp

Text {
width: parent.width
text: qsTr("Scan the QR code")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font: __style.t1
wrapMode: Text.WordWrap
color: __style.whiteColor
}

Text {
width: parent.width
text: qsTr("Please make sure that the lense is clear.")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font: __style.p5
wrapMode: Text.WordWrap
color: __style.whiteColor
}
}
}

Image {
id: closeButton

anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 20 * __dp
source: __style.closeButtonIcon

MouseArea {
anchors.fill: parent
onClicked: {
unload()
close()
}
}
}

function unload() {
qrcodeScanner.videoSink = null
camera.active = false
captureSession.videoOutput = null
captureSession.camera = null
}
}
2 changes: 0 additions & 2 deletions app/qml/inputs/MMPasswordEditor.qml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import "../components"

MMAbstractEditor {
Expand Down
86 changes: 86 additions & 0 deletions app/qml/inputs/MMQrCodeEditor.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import "../components"

MMAbstractEditor {
id: root

property var parentValue: parent.value
property bool isReadOnly: parent.readOnly ?? false

property alias placeholderText: textField.placeholderText
property alias text: textField.text

signal editorValueChanged( var newValue, bool isNull )

hasFocus: textField.activeFocus
enabled: !root.isReadOnly

content: TextField {
id: textField

anchors.fill: parent
anchors.verticalCenter: parent.verticalCenter

text: root.parentValue !== undefined ? root.parentValue : ''
readOnly: !root.enabled
color: root.enabled ? __style.nightColor : __style.mediumGreenColor
placeholderTextColor: __style.nightAlphaColor
font: __style.p5
hoverEnabled: true
background: Rectangle {
color: __style.transparentColor
}
}

rightAction: MMIcon {
property bool pressed: false

height: parent.height

source: __style.qrCodeIcon
color: root.enabled ? __style.forestColor : __style.mediumGreenColor
}

onRightActionClicked: {
if ( !root.enabled )
return
if (!__inputUtils.acquireCameraPermission())
return
codeScannerLoader.active = true
codeScannerLoader.focus = true
}

Loader {
id: codeScannerLoader

asynchronous: true
active: false
sourceComponent: readerComponent
}

Component {
id: readerComponent

MMCodeScanner {
focus: true

Component.onCompleted: open()
onClosed: codeScannerLoader.active = false
onScanFinished: function( captured ) {
root.editorValueChanged( captured, false )
codeScannerLoader.active = false
}
}
}
}
5 changes: 4 additions & 1 deletion gallery/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ find_package(
Svg
Core
Core5Compat
Multimedia
REQUIRED
)

Expand All @@ -31,6 +32,8 @@ qt_policy(SET QTP0001 NEW)

set(GALLERY_HDRS
helper.h
qrcodedecoder.h
inpututils.h
../app/notificationmodel.h
../app/mmstyle.h
../core/merginerrortypes.h
Expand Down Expand Up @@ -78,7 +81,7 @@ set_target_properties(
WIN32_EXECUTABLE TRUE
)

target_link_libraries(MerginMapsGallery PRIVATE Qt6::Quick)
target_link_libraries(MerginMapsGallery PRIVATE Qt6::Quick Qt6::Multimedia)
target_include_directories(MerginMapsGallery PRIVATE ../app ../core)

install(
Expand Down
16 changes: 16 additions & 0 deletions gallery/inpututils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef INPUTUTILS_H
#define INPUTUTILS_H

#include <QObject>

class InputUtils: public QObject
{
Q_OBJECT

public:
explicit InputUtils( QObject *parent = nullptr ) {};

Q_INVOKABLE bool acquireCameraPermission() { return true; }
};

#endif // INPUTUTILS_H
6 changes: 5 additions & 1 deletion gallery/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include <QFontDatabase>
#include "notificationmodel.h"
#include "merginerrortypes.h"
#include "qrcodedecoder.h"
#include "inpututils.h"

int main( int argc, char *argv[] )
{
Expand All @@ -30,12 +32,14 @@ int main( int argc, char *argv[] )

// Register C++ enums
qmlRegisterUncreatableType<RegistrationError>( "lc", 1, 0, "RegistrationError", "RegistrationError Enum" );

qmlRegisterType<QrCodeDecoder>( "lc", 1, 0, "QrCodeDecoder" );

#ifdef DESKTOP_OS
HotReload hotReload( engine );
engine.rootContext()->setContextProperty( "_hotReload", &hotReload );
#endif
InputUtils iu;
engine.rootContext()->setContextProperty( "__inputUtils", &iu );

qreal dp = Helper::calculateDpRatio();
MMStyle style( dp );
Expand Down
2 changes: 2 additions & 0 deletions gallery/qml.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,7 @@
<file>../app/qml/inputs/MMNumberEditor.qml</file>
<file>../app/qml/inputs/MMButtonInputEditor.qml</file>
<file>../app/qml/components/MMWarningBubble.qml</file>
<file>../app/qml/inputs/MMQrCodeEditor.qml</file>
<file>../app/qml/components/MMCodeScanner.qml</file>
</qresource>
</RCC>
10 changes: 10 additions & 0 deletions gallery/qml/pages/EditorsPage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ ScrollView {
checkboxChecked: false
}

MMQrCodeEditor {
title: "MMQrCodeEditor"
placeholderText: "QR code"
warningMsg: text.length > 0 ? "" : "Click to icon and scan the code"
enabled: checkbox.checked
width: parent.width

onEditorValueChanged: function(newValue, isNull) { console.log("QR code: " + newValue) }
}

MMButtonInputEditor {
title: "MMButtonInputEditor"
placeholderText: "Write something"
Expand Down
28 changes: 28 additions & 0 deletions gallery/qrcodedecoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef QRCODEDECODER_H
#define QRCODEDECODER_H

#include <QObject>
#include <QPointer>

class QrCodeDecoder : public QObject
{
Q_OBJECT

Q_PROPERTY( QObject *videoSink READ videoSink WRITE setVideoSink NOTIFY videoSinkChanged );

public:

explicit QrCodeDecoder( QObject *parent = nullptr ) {};

QObject *videoSink() {return nullptr;};
void setVideoSink( QObject *videoSink ) {};

signals:
void codeScanned( const QString &codeData );
void videoSinkChanged();

private:
QPointer<QObject> mVideoSink;
};

#endif // QRCODEDECODER_H

1 comment on commit 5da384e

@inputapp-bot
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iOS - version 24.01.506011 just submitted!

Please sign in to comment.