Support of multiple-code config
This commit is contained in:
parent
a86e8659f7
commit
b870306c5d
11 changed files with 126 additions and 204 deletions
|
@ -34,6 +34,7 @@
|
||||||
android:extractNativeLibs="true"
|
android:extractNativeLibs="true"
|
||||||
android:requestLegacyExternalStorage="true"
|
android:requestLegacyExternalStorage="true"
|
||||||
android:allowNativeHeapPointerTagging="false"
|
android:allowNativeHeapPointerTagging="false"
|
||||||
|
android:theme="@style/Theme.AppCompat.NoActionBar"
|
||||||
android:icon="@drawable/icon">
|
android:icon="@drawable/icon">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
|
@ -115,7 +116,7 @@
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".CameraActivity"
|
android:name=".qt.CameraActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
|
|
|
@ -31,6 +31,20 @@ class CameraActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private lateinit var viewFinder: PreviewView
|
private lateinit var viewFinder: PreviewView
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private lateinit var instance: CameraActivity
|
||||||
|
|
||||||
|
@JvmStatic fun getInstance(): CameraActivity {
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic fun stopQrCodeReader() {
|
||||||
|
CameraActivity.getInstance().finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
external fun passDataToDecoder(data: String)
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_camera)
|
setContentView(R.layout.activity_camera)
|
||||||
|
@ -40,6 +54,8 @@ class CameraActivity : AppCompatActivity() {
|
||||||
cameraExecutor = Executors.newSingleThreadExecutor()
|
cameraExecutor = Executors.newSingleThreadExecutor()
|
||||||
analyzerExecutor = Executors.newSingleThreadExecutor()
|
analyzerExecutor = Executors.newSingleThreadExecutor()
|
||||||
|
|
||||||
|
instance = this
|
||||||
|
|
||||||
checkPermissions()
|
checkPermissions()
|
||||||
|
|
||||||
configureVideoPreview()
|
configureVideoPreview()
|
||||||
|
@ -74,20 +90,7 @@ class CameraActivity : AppCompatActivity() {
|
||||||
|
|
||||||
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
||||||
|
|
||||||
val listener = object : OnBarcodeActivityResult {
|
val imageAnalyzer = BarCodeAnalyzer()
|
||||||
override fun onSuccess(result: String) {
|
|
||||||
val resultIntent = Intent()
|
|
||||||
resultIntent.putExtra("result", result)
|
|
||||||
setResult(Activity.RESULT_OK, resultIntent)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(result: Exception) {
|
|
||||||
Log.d("WUTT", "exception: $result")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val imageAnalyzer = BarCodeAnalyzer(listener)
|
|
||||||
|
|
||||||
val analysisUseCase = ImageAnalysis.Builder()
|
val analysisUseCase = ImageAnalysis.Builder()
|
||||||
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
|
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
|
||||||
|
@ -112,7 +115,9 @@ class CameraActivity : AppCompatActivity() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BarCodeAnalyzer(val callback: OnBarcodeActivityResult): ImageAnalysis.Analyzer {
|
val barcodesSet = mutableSetOf<String>()
|
||||||
|
|
||||||
|
private inner class BarCodeAnalyzer(): ImageAnalysis.Analyzer {
|
||||||
|
|
||||||
private val options = BarcodeScannerOptions.Builder()
|
private val options = BarcodeScannerOptions.Builder()
|
||||||
.setBarcodeFormats(Barcode.FORMAT_QR_CODE)
|
.setBarcodeFormats(Barcode.FORMAT_QR_CODE)
|
||||||
|
@ -130,21 +135,24 @@ class CameraActivity : AppCompatActivity() {
|
||||||
scanner.process(image)
|
scanner.process(image)
|
||||||
.addOnSuccessListener { barcodes ->
|
.addOnSuccessListener { barcodes ->
|
||||||
if (barcodes.isNotEmpty()) {
|
if (barcodes.isNotEmpty()) {
|
||||||
callback.onSuccess(barcodes[0]?.displayValue ?: "empty?")
|
val barcode = barcodes[0]
|
||||||
|
if (barcode != null) {
|
||||||
|
val str = barcode?.displayValue ?: ""
|
||||||
|
if (str.isNotEmpty()) {
|
||||||
|
val isAdded = barcodesSet.add(str)
|
||||||
|
if (isAdded) {
|
||||||
|
passDataToDecoder(str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
imageProxy.close()
|
imageProxy.close()
|
||||||
}
|
}
|
||||||
.addOnFailureListener {
|
.addOnFailureListener {
|
||||||
callback.onFailure(it)
|
|
||||||
imageProxy.close()
|
imageProxy.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OnBarcodeActivityResult {
|
|
||||||
fun onSuccess(result: String)
|
|
||||||
fun onFailure(result: Exception)
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -15,7 +15,6 @@
|
||||||
#include "private/qandroidextras_p.h"
|
#include "private/qandroidextras_p.h"
|
||||||
#include "ui/pages_logic/StartPageLogic.h"
|
#include "ui/pages_logic/StartPageLogic.h"
|
||||||
|
|
||||||
#include "androidvpnactivity.h"
|
|
||||||
#include "androidutils.h"
|
#include "androidutils.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -262,6 +261,11 @@ void AndroidController::setVpnConfig(const QJsonObject &newVpnConfig)
|
||||||
m_vpnConfig = newVpnConfig;
|
m_vpnConfig = newVpnConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AndroidController::startQrReaderActivity()
|
||||||
|
{
|
||||||
|
AndroidVPNActivity::instance()->startQrCodeReader();
|
||||||
|
}
|
||||||
|
|
||||||
void AndroidController::scheduleStatusCheckSlot()
|
void AndroidController::scheduleStatusCheckSlot()
|
||||||
{
|
{
|
||||||
QTimer::singleShot(1000, [this]() {
|
QTimer::singleShot(1000, [this]() {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "ui/pages_logic/StartPageLogic.h"
|
#include "ui/pages_logic/StartPageLogic.h"
|
||||||
|
|
||||||
#include "protocols/vpnprotocol.h"
|
#include "protocols/vpnprotocol.h"
|
||||||
|
#include "androidvpnactivity.h"
|
||||||
|
|
||||||
using namespace amnezia;
|
using namespace amnezia;
|
||||||
|
|
||||||
|
@ -42,6 +43,8 @@ public:
|
||||||
const QJsonObject &vpnConfig() const;
|
const QJsonObject &vpnConfig() const;
|
||||||
void setVpnConfig(const QJsonObject &newVpnConfig);
|
void setVpnConfig(const QJsonObject &newVpnConfig);
|
||||||
|
|
||||||
|
void startQrReaderActivity();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void connectionStateChanged(VpnProtocol::VpnConnectionState state);
|
void connectionStateChanged(VpnProtocol::VpnConnectionState state);
|
||||||
|
|
||||||
|
@ -50,8 +53,7 @@ signals:
|
||||||
// to true and the "connectionDate" should be set to the activation date if
|
// to true and the "connectionDate" should be set to the activation date if
|
||||||
// known.
|
// known.
|
||||||
// If "status" is set to false, the backend service is considered unavailable.
|
// If "status" is set to false, the backend service is considered unavailable.
|
||||||
void initialized(bool status, bool connected,
|
void initialized(bool status, bool connected, const QDateTime& connectionDate);
|
||||||
const QDateTime& connectionDate);
|
|
||||||
|
|
||||||
void statusUpdated(QString totalRx, QString totalTx, QString endpoint, QString deviceIPv4);
|
void statusUpdated(QString totalRx, QString totalTx, QString endpoint, QString deviceIPv4);
|
||||||
void scheduleStatusCheckSignal();
|
void scheduleStatusCheckSignal();
|
||||||
|
@ -59,9 +61,6 @@ signals:
|
||||||
protected slots:
|
protected slots:
|
||||||
void scheduleStatusCheckSlot();
|
void scheduleStatusCheckSlot();
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_init = false;
|
bool m_init = false;
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,6 @@
|
||||||
<file>ui/qml/Pages/PageSites.qml</file>
|
<file>ui/qml/Pages/PageSites.qml</file>
|
||||||
<file>ui/qml/Pages/PageStart.qml</file>
|
<file>ui/qml/Pages/PageStart.qml</file>
|
||||||
<file>ui/qml/Pages/PageVPN.qml</file>
|
<file>ui/qml/Pages/PageVPN.qml</file>
|
||||||
<file>ui/qml/Pages/PageQrDecoder.qml</file>
|
|
||||||
<file>ui/qml/Pages/PageAbout.qml</file>
|
<file>ui/qml/Pages/PageAbout.qml</file>
|
||||||
<file>ui/qml/Pages/PageQrDecoderIos.qml</file>
|
<file>ui/qml/Pages/PageQrDecoderIos.qml</file>
|
||||||
<file>ui/qml/Pages/PageViewConfig.qml</file>
|
<file>ui/qml/Pages/PageViewConfig.qml</file>
|
||||||
|
|
|
@ -3,15 +3,70 @@
|
||||||
#include "ui/uilogic.h"
|
#include "ui/uilogic.h"
|
||||||
#include "ui/pages_logic/StartPageLogic.h"
|
#include "ui/pages_logic/StartPageLogic.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
#include <QJniEnvironment>
|
||||||
|
#include <QJniObject>
|
||||||
|
#include "../../platforms/android/androidutils.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace amnezia;
|
using namespace amnezia;
|
||||||
using namespace PageEnumNS;
|
using namespace PageEnumNS;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
QrDecoderLogic* mInstance = nullptr;
|
||||||
|
constexpr auto CLASSNAME = "org.amnezia.vpn.qt.CameraActivity";
|
||||||
|
}
|
||||||
|
|
||||||
QrDecoderLogic::QrDecoderLogic(UiLogic *logic, QObject *parent):
|
QrDecoderLogic::QrDecoderLogic(UiLogic *logic, QObject *parent):
|
||||||
PageLogicBase(logic, parent)
|
PageLogicBase(logic, parent)
|
||||||
{
|
{
|
||||||
|
mInstance = this;
|
||||||
|
|
||||||
|
#if (defined(Q_OS_ANDROID))
|
||||||
|
AndroidUtils::runOnAndroidThreadAsync([]() {
|
||||||
|
JNINativeMethod methods[]{
|
||||||
|
{"passDataToDecoder", "(Ljava/lang/String;)V", reinterpret_cast<void*>(onNewDataChunk)},
|
||||||
|
};
|
||||||
|
|
||||||
|
QJniObject javaClass(CLASSNAME);
|
||||||
|
QJniEnvironment env;
|
||||||
|
jclass objectClass = env->GetObjectClass(javaClass.object<jobject>());
|
||||||
|
env->RegisterNatives(objectClass, methods, sizeof(methods) / sizeof(methods[0]));
|
||||||
|
env->DeleteLocalRef(objectClass);
|
||||||
|
});
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QrDecoderLogic::stopDecodingQr()
|
||||||
|
{
|
||||||
|
#if (defined(Q_OS_ANDROID))
|
||||||
|
QJniObject::callStaticMethod<void>(CLASSNAME, "stopQrCodeReader", "()V");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
emit stopDecode();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
void QrDecoderLogic::onNewDataChunk(JNIEnv *env, jobject thiz, jstring data)
|
||||||
|
{
|
||||||
|
Q_UNUSED(thiz);
|
||||||
|
const char* buffer = env->GetStringUTFChars(data, nullptr);
|
||||||
|
if (!buffer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString parcelBody(buffer);
|
||||||
|
env->ReleaseStringUTFChars(data, buffer);
|
||||||
|
|
||||||
|
if (mInstance != nullptr) {
|
||||||
|
if (!mInstance->m_detectingEnabled) {
|
||||||
|
mInstance->onUpdatePage();
|
||||||
|
}
|
||||||
|
mInstance->onDetectedQrCode(parcelBody);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void QrDecoderLogic::onUpdatePage()
|
void QrDecoderLogic::onUpdatePage()
|
||||||
{
|
{
|
||||||
m_chunks.clear();
|
m_chunks.clear();
|
||||||
|
@ -24,7 +79,6 @@ void QrDecoderLogic::onUpdatePage()
|
||||||
void QrDecoderLogic::onDetectedQrCode(const QString &code)
|
void QrDecoderLogic::onDetectedQrCode(const QString &code)
|
||||||
{
|
{
|
||||||
//qDebug() << code;
|
//qDebug() << code;
|
||||||
|
|
||||||
if (!detectingEnabled()) return;
|
if (!detectingEnabled()) return;
|
||||||
|
|
||||||
// check if chunk received
|
// check if chunk received
|
||||||
|
@ -32,12 +86,12 @@ void QrDecoderLogic::onDetectedQrCode(const QString &code)
|
||||||
QDataStream s(&ba, QIODevice::ReadOnly);
|
QDataStream s(&ba, QIODevice::ReadOnly);
|
||||||
qint16 magic; s >> magic;
|
qint16 magic; s >> magic;
|
||||||
|
|
||||||
|
|
||||||
if (magic == amnezia::qrMagicCode) {
|
if (magic == amnezia::qrMagicCode) {
|
||||||
quint8 chunksCount; s >> chunksCount;
|
quint8 chunksCount; s >> chunksCount;
|
||||||
if (totalChunksCount() != chunksCount) {
|
if (totalChunksCount() != chunksCount) {
|
||||||
m_chunks.clear();
|
m_chunks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
set_totalChunksCount(chunksCount);
|
set_totalChunksCount(chunksCount);
|
||||||
|
|
||||||
quint8 chunkId; s >> chunkId;
|
quint8 chunkId; s >> chunkId;
|
||||||
|
@ -46,6 +100,7 @@ void QrDecoderLogic::onDetectedQrCode(const QString &code)
|
||||||
|
|
||||||
if (m_chunks.size() == totalChunksCount()) {
|
if (m_chunks.size() == totalChunksCount()) {
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
|
|
||||||
for (int i = 0; i < totalChunksCount(); ++i) {
|
for (int i = 0; i < totalChunksCount(); ++i) {
|
||||||
data.append(m_chunks.value(i));
|
data.append(m_chunks.value(i));
|
||||||
}
|
}
|
||||||
|
@ -53,21 +108,18 @@ void QrDecoderLogic::onDetectedQrCode(const QString &code)
|
||||||
bool ok = uiLogic()->pageLogic<StartPageLogic>()->importConnectionFromQr(data);
|
bool ok = uiLogic()->pageLogic<StartPageLogic>()->importConnectionFromQr(data);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
set_detectingEnabled(false);
|
set_detectingEnabled(false);
|
||||||
emit stopDecode();
|
stopDecodingQr();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
m_chunks.clear();
|
m_chunks.clear();
|
||||||
set_totalChunksCount(0);
|
set_totalChunksCount(0);
|
||||||
set_receivedChunksCount(0);
|
set_receivedChunksCount(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
bool ok = uiLogic()->pageLogic<StartPageLogic>()->importConnectionFromQr(ba);
|
bool ok = uiLogic()->pageLogic<StartPageLogic>()->importConnectionFromQr(ba);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
set_detectingEnabled(false);
|
set_detectingEnabled(false);
|
||||||
emit stopDecode();
|
stopDecodingQr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
|
|
||||||
#include "PageLogicBase.h"
|
#include "PageLogicBase.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
#include "jni.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class UiLogic;
|
class UiLogic;
|
||||||
|
|
||||||
class QrDecoderLogic : public PageLogicBase
|
class QrDecoderLogic : public PageLogicBase
|
||||||
|
@ -16,10 +20,17 @@ public:
|
||||||
Q_INVOKABLE void onUpdatePage() override;
|
Q_INVOKABLE void onUpdatePage() override;
|
||||||
Q_INVOKABLE void onDetectedQrCode(const QString &code);
|
Q_INVOKABLE void onDetectedQrCode(const QString &code);
|
||||||
|
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
static void onNewDataChunk(JNIEnv *env, jobject thiz, jstring data);
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QrDecoderLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
explicit QrDecoderLogic(UiLogic *uiLogic, QObject *parent = nullptr);
|
||||||
~QrDecoderLogic() = default;
|
~QrDecoderLogic() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void stopDecodingQr();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void startDecode();
|
void startDecode();
|
||||||
void stopDecode();
|
void stopDecode();
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
#include <QJniObject>
|
#include <QJniObject>
|
||||||
#include "../../platforms/android/androidutils.h"
|
#include "../../platforms/android/androidutils.h"
|
||||||
|
#include "../../platforms/android/android_controller.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -184,6 +185,13 @@ void StartPageLogic::onPushButtonImportOpenFile()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
void StartPageLogic::startQrDecoder()
|
||||||
|
{
|
||||||
|
AndroidController::instance()->startQrReaderActivity();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool StartPageLogic::importConnection(const QJsonObject &profile)
|
bool StartPageLogic::importConnection(const QJsonObject &profile)
|
||||||
{
|
{
|
||||||
ServerCredentials credentials;
|
ServerCredentials credentials;
|
||||||
|
|
|
@ -31,6 +31,10 @@ public:
|
||||||
Q_INVOKABLE void onPushButtonImport();
|
Q_INVOKABLE void onPushButtonImport();
|
||||||
Q_INVOKABLE void onPushButtonImportOpenFile();
|
Q_INVOKABLE void onPushButtonImportOpenFile();
|
||||||
|
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
Q_INVOKABLE void startQrDecoder();
|
||||||
|
#endif
|
||||||
|
|
||||||
bool importConnection(const QJsonObject &profile);
|
bool importConnection(const QJsonObject &profile);
|
||||||
bool importConnectionFromCode(QString code);
|
bool importConnectionFromCode(QString code);
|
||||||
bool importConnectionFromQr(const QByteArray &data);
|
bool importConnectionFromQr(const QByteArray &data);
|
||||||
|
|
|
@ -1,164 +0,0 @@
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import QtMultimedia
|
|
||||||
import PageEnum 1.0
|
|
||||||
import QZXing 3.2
|
|
||||||
|
|
||||||
import "./"
|
|
||||||
import "../Controls"
|
|
||||||
import "../Config"
|
|
||||||
|
|
||||||
PageBase {
|
|
||||||
id: root
|
|
||||||
page: PageEnum.QrDecoder
|
|
||||||
logic: QrDecoderLogic
|
|
||||||
|
|
||||||
onDeactivated: {
|
|
||||||
console.debug("Stopping QR decoder")
|
|
||||||
loader.sourceComponent = undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
BackButton {
|
|
||||||
}
|
|
||||||
Caption {
|
|
||||||
id: caption
|
|
||||||
text: qsTr("Import configuration")
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: Qt.platform.os != "ios" ? QrDecoderLogic : null
|
|
||||||
function onStartDecode() {
|
|
||||||
console.debug("Starting QR decoder")
|
|
||||||
loader.sourceComponent = component
|
|
||||||
}
|
|
||||||
function onStopDecode() {
|
|
||||||
console.debug("Stopping QR decoder")
|
|
||||||
loader.sourceComponent = undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: loader
|
|
||||||
|
|
||||||
anchors.top: caption.bottom
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: component
|
|
||||||
|
|
||||||
Item {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Camera
|
|
||||||
{
|
|
||||||
id:camera
|
|
||||||
focus {
|
|
||||||
focusMode: CameraFocus.FocusContinuous
|
|
||||||
focusPointMode: CameraFocus.FocusPointAuto
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VideoOutput
|
|
||||||
{
|
|
||||||
id: videoOutput
|
|
||||||
source: camera
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
autoOrientation: true
|
|
||||||
fillMode: VideoOutput.PreserveAspectFit
|
|
||||||
// filters: [ zxingFilter ]
|
|
||||||
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
color: "black"
|
|
||||||
opacity: 0.5
|
|
||||||
width: videoOutput.contentRect.width * 0.15
|
|
||||||
height: videoOutput.contentRect.height
|
|
||||||
x: (videoOutput.width - videoOutput.contentRect.width)/2
|
|
||||||
anchors.verticalCenter: videoOutput.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
color: "black"
|
|
||||||
opacity: 0.5
|
|
||||||
width: videoOutput.contentRect.width * 0.15
|
|
||||||
height: videoOutput.contentRect.height
|
|
||||||
x: videoOutput.width/2 + videoOutput.contentRect.width/2 - videoOutput.contentRect.width * 0.15
|
|
||||||
anchors.verticalCenter: videoOutput.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
color: "black"
|
|
||||||
opacity: 0.5
|
|
||||||
width: videoOutput.contentRect.width * 0.7
|
|
||||||
height: videoOutput.contentRect.height * 0.15
|
|
||||||
x: (videoOutput.width - videoOutput.contentRect.width)/2 + videoOutput.contentRect.width * 0.15
|
|
||||||
y: (videoOutput.height - videoOutput.contentRect.height)/2
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
color: "black"
|
|
||||||
opacity: 0.5
|
|
||||||
width: videoOutput.contentRect.width * 0.7
|
|
||||||
height: videoOutput.contentRect.height * 0.15
|
|
||||||
x: (videoOutput.width - videoOutput.contentRect.width)/2 + videoOutput.contentRect.width * 0.15
|
|
||||||
y: videoOutput.height/2 + videoOutput.contentRect.height/2 - videoOutput.contentRect.height * 0.15
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelType {
|
|
||||||
width: parent.width
|
|
||||||
text: qsTr("Decoded QR chunks " + QrDecoderLogic.receivedChunksCount + "/" + QrDecoderLogic.totalChunksCount)
|
|
||||||
horizontalAlignment: Text.AlignLeft
|
|
||||||
visible: QrDecoderLogic.totalChunksCount > 0
|
|
||||||
anchors.horizontalCenter: videoOutput.horizontalCenter
|
|
||||||
y: videoOutput.height/2 + videoOutput.contentRect.height/2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QZXingFilter
|
|
||||||
{
|
|
||||||
id: zxingFilter
|
|
||||||
orientation: videoOutput.orientation
|
|
||||||
captureRect: {
|
|
||||||
// setup bindings
|
|
||||||
videoOutput.contentRect;
|
|
||||||
videoOutput.sourceRect;
|
|
||||||
return videoOutput.mapRectToSource(videoOutput.mapNormalizedRectToItem(Qt.rect(
|
|
||||||
0.15, 0.15, 0.7, 0.7 //0, 0, 1.0, 1.0
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
decoder {
|
|
||||||
enabledDecoders: QZXing.DecoderFormat_QR_CODE
|
|
||||||
|
|
||||||
onTagFound: {
|
|
||||||
QrDecoderLogic.onDetectedQrCode(tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
tryHarder: true
|
|
||||||
}
|
|
||||||
|
|
||||||
property int framesDecoded: 0
|
|
||||||
property real timePerFrameDecode: 0
|
|
||||||
|
|
||||||
onDecodingFinished:
|
|
||||||
{
|
|
||||||
timePerFrameDecode = (decodeTime + framesDecoded * timePerFrameDecode) / (framesDecoded + 1);
|
|
||||||
framesDecoded++;
|
|
||||||
if(succeeded)
|
|
||||||
console.log("frame finished: " + succeeded, decodeTime, timePerFrameDecode, framesDecoded);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -154,7 +154,7 @@ PageBase {
|
||||||
if (Qt.platform.os === "ios") {
|
if (Qt.platform.os === "ios") {
|
||||||
UiLogic.goToPage(PageEnum.QrDecoderIos)
|
UiLogic.goToPage(PageEnum.QrDecoderIos)
|
||||||
} else {
|
} else {
|
||||||
UiLogic.goToPage(PageEnum.QrDecoder)
|
StartPageLogic.startQrDecoder()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enabled: StartPageLogic.pushButtonConnectEnabled
|
enabled: StartPageLogic.pushButtonConnectEnabled
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue