12 changed files with 234 additions and 191 deletions
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
|
||||
<FrameLayout |
||||
xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent"> |
||||
|
||||
<FrameLayout |
||||
android:id="@+id/content_frame" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" /> |
||||
|
||||
<TextView |
||||
android:id="@+id/hint" |
||||
android:layout_gravity="center|top" |
||||
android:text="Scan a QR code." |
||||
android:layout_width="wrap_content" |
||||
android:textColor="#ffffff" |
||||
android:layout_height="wrap_content" /> |
||||
|
||||
<Button |
||||
android:id="@+id/paste_btn" |
||||
android:layout_gravity="center|bottom" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="wrap_content" |
||||
android:text="Paste from clipboard" /> |
||||
|
||||
</FrameLayout> |
||||
@ -1,51 +0,0 @@
|
||||
import QtQuick |
||||
import QtQuick.Controls |
||||
import QtQuick.Layouts |
||||
|
||||
import "controls" |
||||
|
||||
ElDialog { |
||||
id: scanDialog |
||||
|
||||
property string scanData |
||||
property string error |
||||
property string hint |
||||
|
||||
signal found |
||||
|
||||
width: parent.width |
||||
height: parent.height |
||||
padding: 0 |
||||
|
||||
header: null |
||||
topPadding: 0 // dialog needs topPadding override |
||||
|
||||
function doClose() { |
||||
qrscan.stop() |
||||
Qt.callLater(doReject) |
||||
} |
||||
|
||||
ColumnLayout { |
||||
anchors.fill: parent |
||||
spacing: 0 |
||||
|
||||
QRScan { |
||||
id: qrscan |
||||
Layout.fillWidth: true |
||||
Layout.fillHeight: true |
||||
hint: scanDialog.hint |
||||
onFound: { |
||||
scanDialog.scanData = scanData |
||||
scanDialog.found() |
||||
} |
||||
} |
||||
|
||||
FlatButton { |
||||
id: button |
||||
Layout.fillWidth: true |
||||
text: qsTr('Cancel') |
||||
icon.source: '../../icons/closebutton.png' |
||||
onClicked: doReject() |
||||
} |
||||
} |
||||
} |
||||
@ -1,82 +0,0 @@
|
||||
import QtQuick |
||||
import QtQuick.Controls |
||||
import QtQuick.Layouts |
||||
import QtQuick.Controls.Material |
||||
|
||||
import org.electrum 1.0 |
||||
|
||||
import "controls" |
||||
|
||||
ElDialog { |
||||
id: dialog |
||||
|
||||
property InvoiceParser invoiceParser |
||||
|
||||
signal txFound(data: string) |
||||
signal channelBackupFound(data: string) |
||||
|
||||
header: null |
||||
padding: 0 |
||||
topPadding: 0 |
||||
|
||||
onAboutToHide: { |
||||
console.log('about to hide') |
||||
qrscan.stop() |
||||
} |
||||
|
||||
function restart() { |
||||
qrscan.restart() |
||||
} |
||||
|
||||
function dispatch(data) { |
||||
data = data.trim() |
||||
if (bitcoin.isRawTx(data)) { |
||||
txFound(data) |
||||
} else if (Daemon.currentWallet.isValidChannelBackup(data)) { |
||||
channelBackupFound(data) |
||||
} else { |
||||
invoiceParser.recipient = data |
||||
} |
||||
} |
||||
|
||||
// override |
||||
function doClose() { |
||||
console.log('SendDialog doClose override') // doesn't trigger when going back?? |
||||
qrscan.stop() |
||||
Qt.callLater(doReject) |
||||
} |
||||
|
||||
ColumnLayout { |
||||
anchors.fill: parent |
||||
spacing: 0 |
||||
|
||||
QRScan { |
||||
id: qrscan |
||||
Layout.fillWidth: true |
||||
Layout.fillHeight: true |
||||
|
||||
hint: qsTr('Scan an Invoice, an Address, an LNURL-pay, a PSBT or a Channel backup') |
||||
onFound: dialog.dispatch(scanData) |
||||
} |
||||
|
||||
ButtonContainer { |
||||
Layout.fillWidth: true |
||||
|
||||
FlatButton { |
||||
Layout.fillWidth: true |
||||
Layout.preferredWidth: 1 |
||||
icon.source: '../../icons/copy_bw.png' |
||||
text: qsTr('Paste') |
||||
onClicked: { |
||||
qrscan.stop() |
||||
dialog.dispatch(AppController.clipboardToText()) |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
Bitcoin { |
||||
id: bitcoin |
||||
} |
||||
} |
||||
@ -0,0 +1,96 @@
|
||||
import os |
||||
|
||||
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject |
||||
from PyQt6.QtGui import QGuiApplication |
||||
|
||||
from electrum.util import send_exception_to_crash_reporter, UserFacingException |
||||
from electrum.simple_config import SimpleConfig |
||||
from electrum.logging import get_logger |
||||
from electrum.i18n import _ |
||||
|
||||
|
||||
if 'ANDROID_DATA' in os.environ: |
||||
from jnius import autoclass, cast |
||||
from android import activity |
||||
|
||||
jpythonActivity = autoclass('org.kivy.android.PythonActivity').mActivity |
||||
jString = autoclass('java.lang.String') |
||||
jIntent = autoclass('android.content.Intent') |
||||
|
||||
|
||||
class QEQRScanner(QObject): |
||||
_logger = get_logger(__name__) |
||||
|
||||
found = pyqtSignal() |
||||
|
||||
def __init__(self, parent=None): |
||||
super().__init__(parent) |
||||
self._hint = _("Scan a QR code.") |
||||
self._scan_data = "" # decoded qr code result |
||||
|
||||
@pyqtProperty(str) |
||||
def hint(self): |
||||
return self._hint |
||||
|
||||
@hint.setter |
||||
def hint(self, v: str): |
||||
self._hint = v |
||||
|
||||
@pyqtProperty(str) |
||||
def scanData(self): |
||||
return self._scan_data |
||||
|
||||
@scanData.setter |
||||
def scanData(self, v: str): |
||||
self._scan_data = v |
||||
|
||||
@pyqtSlot() |
||||
def open(self): |
||||
if 'ANDROID_DATA' not in os.environ: |
||||
self._scan_qr_non_android() |
||||
return |
||||
SimpleScannerActivity = autoclass("org.electrum.qr.SimpleScannerActivity") |
||||
intent = jIntent(jpythonActivity, SimpleScannerActivity) |
||||
intent.putExtra(jIntent.EXTRA_TEXT, jString(self._hint)) |
||||
|
||||
def on_qr_result(requestCode, resultCode, intent): |
||||
try: |
||||
if resultCode == -1: # RESULT_OK: |
||||
# this doesn't work due to some bug in jnius: |
||||
# contents = intent.getStringExtra("text") |
||||
contents = intent.getStringExtra(jString("text")) |
||||
#self._logger.info(f"on_qr_result. {contents=!r}") |
||||
self.scanData = contents |
||||
self.found.emit() |
||||
except Exception as e: # exc would otherwise get lost |
||||
send_exception_to_crash_reporter(e) |
||||
finally: |
||||
activity.unbind(on_activity_result=on_qr_result) |
||||
activity.bind(on_activity_result=on_qr_result) |
||||
jpythonActivity.startActivityForResult(intent, 0) |
||||
|
||||
@pyqtSlot() |
||||
def close(self): |
||||
pass |
||||
|
||||
def _scan_qr_non_android(self): |
||||
data = QGuiApplication.clipboard().text() |
||||
self.scanData = data |
||||
self.found.emit() |
||||
return |
||||
# from electrum import qrscanner |
||||
# from .qeapp import ElectrumQmlApplication |
||||
# daemon = ElectrumQmlApplication._daemon |
||||
# config = daemon.config # type: SimpleConfig |
||||
# try: |
||||
# video_dev = config.get_video_device() |
||||
# data = qrscanner.scan_barcode(video_dev) |
||||
# if data is not None: |
||||
# self.scanData = data |
||||
# self.found.emit() |
||||
# except UserFacingException as e: |
||||
# self._logger.warning(f'camera error: {e!r}') |
||||
# #self.show_error(e) |
||||
# except Exception as e: |
||||
# self._logger.exception('camera error') |
||||
# #self.show_error(repr(e)) |
||||
Loading…
Reference in new issue