Browse Source

qml: port PyQt5 to PyQt6

master
Sander van Grieken 2 years ago
parent
commit
6270eae5c9
  1. 2
      electrum/gui/common_qt/plugins.py
  2. 2
      electrum/gui/default_lang.py
  3. 25
      electrum/gui/qml/__init__.py
  4. 2
      electrum/gui/qml/auth.py
  5. 6
      electrum/gui/qml/components/Constants.qml
  6. 7
      electrum/gui/qml/components/Wallets.qml
  7. 2
      electrum/gui/qml/components/controls/HistoryItemDelegate.qml
  8. 4
      electrum/gui/qml/components/controls/InvoiceDelegate.qml
  9. 4
      electrum/gui/qml/components/controls/OnchainNetworkStatusIndicator.qml
  10. 62
      electrum/gui/qml/components/controls/QRScan.qml
  11. 71
      electrum/gui/qml/components/main.qml
  12. 2
      electrum/gui/qml/qeaddressdetails.py
  13. 8
      electrum/gui/qml/qeaddresslistmodel.py
  14. 37
      electrum/gui/qml/qeapp.py
  15. 14
      electrum/gui/qml/qebip39recovery.py
  16. 2
      electrum/gui/qml/qebitcoin.py
  17. 8
      electrum/gui/qml/qechanneldetails.py
  18. 8
      electrum/gui/qml/qechannellistmodel.py
  19. 2
      electrum/gui/qml/qechannelopener.py
  20. 2
      electrum/gui/qml/qeconfig.py
  21. 8
      electrum/gui/qml/qedaemon.py
  22. 2
      electrum/gui/qml/qefx.py
  23. 12
      electrum/gui/qml/qeinvoice.py
  24. 8
      electrum/gui/qml/qeinvoicelistmodel.py
  25. 2
      electrum/gui/qml/qelnpaymentdetails.py
  26. 2
      electrum/gui/qml/qemodelfilter.py
  27. 2
      electrum/gui/qml/qenetwork.py
  28. 8
      electrum/gui/qml/qeqr.py
  29. 8
      electrum/gui/qml/qerequestdetails.py
  30. 8
      electrum/gui/qml/qeserverlistmodel.py
  31. 8
      electrum/gui/qml/qeswaphelper.py
  32. 8
      electrum/gui/qml/qetransactionlistmodel.py
  33. 2
      electrum/gui/qml/qetxdetails.py
  34. 2
      electrum/gui/qml/qetxfinalizer.py
  35. 2
      electrum/gui/qml/qetypes.py
  36. 2
      electrum/gui/qml/qewallet.py
  37. 2
      electrum/gui/qml/qewizard.py
  38. 2
      electrum/gui/qml/util.py
  39. 2
      electrum/plugins/labels/qml.py
  40. 2
      electrum/plugins/trustedcoin/common_qt.py
  41. 1
      electrum/plugins/trustedcoin/qml.py

2
electrum/gui/common_qt/plugins.py

@ -1,4 +1,4 @@
from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject
from PyQt6.QtCore import pyqtSignal, pyqtProperty, QObject # TODO: common code, Qt5/Qt6 mismatch!
from electrum.logging import get_logger

2
electrum/gui/default_lang.py

@ -24,7 +24,7 @@ def get_default_language(*, gui_name: Optional[str] = None) -> str:
name = QLocale.system().name()
return name if name in languages else "en_UK"
elif gui_name == "qml":
from PyQt5.QtCore import QLocale
from PyQt6.QtCore import QLocale
# On Android QLocale does not return the system locale
try:
name = str(jLocale.getDefault().toString())

25
electrum/gui/qml/__init__.py

@ -5,17 +5,17 @@ import threading
from typing import TYPE_CHECKING
try:
import PyQt5
import PyQt6
except Exception:
sys.exit("Error: Could not import PyQt5 on Linux systems, you may try 'sudo apt-get install python3-pyqt5'")
sys.exit("Error: Could not import PyQt6 on Linux systems, you may try 'sudo apt-get install python3-pyqt6'")
try:
import PyQt5.QtQml
import PyQt6.QtQml
except Exception:
sys.exit("Error: Could not import PyQt5.QtQml on Linux systems, you may try 'sudo apt-get install python3-pyqt5.qtquick'")
sys.exit("Error: Could not import PyQt6.QtQml on Linux systems, you may try 'sudo apt-get install python3-pyqt6.qtquick'")
from PyQt5.QtCore import (Qt, QCoreApplication, QLocale, QTranslator, QTimer, QT_VERSION_STR, PYQT_VERSION_STR)
from PyQt5.QtGui import QGuiApplication
from PyQt6.QtCore import (Qt, QCoreApplication, QLocale, QTranslator, QTimer, QT_VERSION_STR, PYQT_VERSION_STR)
from PyQt6.QtGui import QGuiApplication
from electrum.i18n import _
from electrum.plugin import run_hook
@ -40,7 +40,6 @@ class ElectrumTranslator(QTranslator):
class ElectrumGui(BaseElectrumGui, Logger):
@profiler
def __init__(self, config: 'SimpleConfig', daemon: 'Daemon', plugins: 'Plugins'):
BaseElectrumGui.__init__(self, config=config, daemon=daemon, plugins=plugins)
@ -63,13 +62,11 @@ class ElectrumGui(BaseElectrumGui, Logger):
# GC-ed when windows are closed
#network.add_jobs([DebugMem([Abstract_Wallet, SPV, Synchronizer,
# ElectrumWindow], interval=5)])
QCoreApplication.setAttribute(Qt.AA_X11InitThreads)
if hasattr(Qt, "AA_ShareOpenGLContexts"):
QCoreApplication.setAttribute(Qt.AA_ShareOpenGLContexts)
if hasattr(QGuiApplication, 'setDesktopFileName'):
QGuiApplication.setDesktopFileName('electrum.desktop')
if hasattr(Qt, "AA_EnableHighDpiScaling"):
QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
if "QT_QUICK_CONTROLS_STYLE" not in os.environ:
os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
@ -100,10 +97,14 @@ class ElectrumGui(BaseElectrumGui, Logger):
return
self.timer.start()
signal.signal(signal.SIGINT, lambda *args: self.stop())
signal.signal(signal.SIGINT, lambda *args: self._handle_sigint())
self.logger.info('Entering main loop')
self.app.exec_()
self.app.exec()
def _handle_sigint(self):
self.app.appController.wantClose = True
self.stop()
def stop(self):
self.logger.info('closing GUI')

2
electrum/gui/qml/auth.py

@ -1,6 +1,6 @@
from functools import wraps, partial
from PyQt5.QtCore import pyqtSignal, pyqtSlot
from PyQt6.QtCore import pyqtSignal, pyqtSlot
from electrum.logging import get_logger

6
electrum/gui/qml/components/Constants.qml

@ -1,8 +1,8 @@
import QtQuick 2.6
import QtQuick.Controls.Material 2.0
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Material
Item {
readonly property int paddingTiny: 4 //deprecated
readonly property int paddingXXSmall: 4
readonly property int paddingXSmall: 6
readonly property int paddingSmall: 8

7
electrum/gui/qml/components/Wallets.qml

@ -27,12 +27,11 @@ Pane {
ColumnLayout {
id: rootLayout
width: parent.width
height: parent.height
anchors.fill: parent
spacing: 0
ColumnLayout {
Layout.preferredWidth: parent.width
Layout.fillWidth: true
Layout.margins: constants.paddingLarge
Heading {
@ -41,7 +40,7 @@ Pane {
Frame {
id: detailsFrame
Layout.preferredWidth: parent.width
Layout.fillWidth: true
Layout.fillHeight: true
verticalPadding: 0
horizontalPadding: 0

2
electrum/gui/qml/components/controls/HistoryItemDelegate.qml

@ -121,7 +121,7 @@ Item {
visible: delegate.ListView.section == delegate.ListView.nextSection
Layout.preferredWidth: parent.width * 2/3
Layout.alignment: Qt.AlignHCenter
Layout.preferredHeight: constants.paddingTiny
Layout.preferredHeight: constants.paddingXXSmall
color: Material.background
}

4
electrum/gui/qml/components/controls/InvoiceDelegate.qml

@ -31,7 +31,7 @@ ItemDelegate {
Rectangle {
Layout.columnSpan: 2
Layout.fillWidth: true
Layout.preferredHeight: constants.paddingTiny
Layout.preferredHeight: constants.paddingXXSmall
color: 'transparent'
}
@ -133,7 +133,7 @@ ItemDelegate {
Rectangle {
Layout.columnSpan: 2
Layout.fillWidth: true
Layout.preferredHeight: constants.paddingTiny
Layout.preferredHeight: constants.paddingXXSmall
color: 'transparent'
}

4
electrum/gui/qml/components/controls/OnchainNetworkStatusIndicator.qml

@ -13,7 +13,7 @@ Image {
property bool proxy: connected && 'mode' in Network.proxy && Network.proxy.mode
// ?: in order to keep this a binding..
source: !connected
source: Qt.resolvedUrl(!connected
? '../../../icons/status_disconnected.png'
: syncing
? '../../../icons/status_waiting.png'
@ -27,7 +27,7 @@ Image {
: '../../../icons/status_connected_fork.png'
: proxy
? '../../../icons/status_connected_proxy.png'
: '../../../icons/status_connected.png'
: '../../../icons/status_connected.png')
states: [

62
electrum/gui/qml/components/controls/QRScan.qml

@ -1,6 +1,6 @@
import QtQuick 2.12
import QtQuick.Controls 2.0
import QtMultimedia 5.6
import QtMultimedia
import org.electrum 1.0
@ -25,7 +25,7 @@ Item {
VideoOutput {
id: vo
anchors.fill: parent
source: camera
// source: camera
fillMode: VideoOutput.PreserveAspectCrop
Rectangle {
@ -114,31 +114,41 @@ Item {
}
}
Camera {
id: camera
deviceId: QtMultimedia.defaultCamera.deviceId
viewfinder.resolution: "640x480"
focus {
focusMode: Camera.FocusContinuous
focusPointMode: Camera.FocusPointCustom
customFocusPoint: Qt.point(0.5, 0.5)
}
MediaDevices {
id: mediaDevices
}
function dumpstats() {
console.log(camera.viewfinder.resolution)
console.log(camera.viewfinder.minimumFrameRate)
console.log(camera.viewfinder.maximumFrameRate)
var resolutions = camera.supportedViewfinderResolutions()
resolutions.forEach(function(item, i) {
console.log('' + item.width + 'x' + item.height)
})
// TODO
// pick a suitable resolution from the available resolutions
// problem: some cameras have no supportedViewfinderResolutions
// but still error out when an invalid resolution is set.
// 640x480 seems to be universally available, but this needs to
// be checked across a range of phone models.
CaptureSession {
videoOutput: VideoOutput
camera: Camera {
id: camera
// deviceId: QtMultimedia.defaultCamera.deviceId
cameraDevice: mediaDevices.defaultVideoInput
// TODO QT6
// viewfinder.resolution: "640x480"
// focus {
// focusMode: Camera.FocusContinuous
// focusPointMode: Camera.FocusPointCustom
// customFocusPoint: Qt.point(0.5, 0.5)
// }
function dumpstats() {
console.log(camera.viewfinder.resolution)
console.log(camera.viewfinder.minimumFrameRate)
console.log(camera.viewfinder.maximumFrameRate)
var resolutions = camera.supportedViewfinderResolutions()
resolutions.forEach(function(item, i) {
console.log('' + item.width + 'x' + item.height)
})
// TODO
// pick a suitable resolution from the available resolutions
// problem: some cameras have no supportedViewfinderResolutions
// but still error out when an invalid resolution is set.
// 640x480 seems to be universally available, but this needs to
// be checked across a range of phone models.
}
}
}

71
electrum/gui/qml/components/main.qml

@ -1,12 +1,13 @@
import QtQuick 2.6
import QtQuick.Layouts 1.0
import QtQuick.Controls 2.3
import QtQuick.Controls.Material 2.0
import QtQuick.Controls.Material.impl 2.12
import QtQuick.Window 2.15
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Controls.Basic
import QtQuick.Controls.Material
import QtQuick.Controls.Material.impl
import QtQuick.Window
import QtQml 2.6
import QtMultimedia 5.6
import QtQml
import QtMultimedia
import org.electrum 1.0
@ -27,14 +28,13 @@ ApplicationWindow
Material.accent: Material.LightBlue
font.pixelSize: constants.fontSizeMedium
property Item constants: appconstants
property QtObject constants: appconstants
Constants { id: appconstants }
property alias stack: mainStackView
property variant activeDialogs: []
property bool _wantClose: false
property var _exceptionDialog
property QtObject appMenu: Menu {
@ -105,7 +105,8 @@ ApplicationWindow
ColumnLayout {
spacing: 0
width: parent.width
anchors.left: parent.left
anchors.right: parent.right
height: toolbar.height
RowLayout {
@ -171,7 +172,6 @@ ApplicationWindow
RowLayout {
id: statusIconsLayout
anchors.verticalCenter: parent.verticalCenter
Item {
Layout.preferredWidth: constants.paddingLarge
Layout.preferredHeight: 1
@ -207,9 +207,12 @@ ApplicationWindow
}
}
WalletSummary {
id: walletSummary
Layout.preferredWidth: app.width
// hack to force relayout of toolbar
// since qt6 watchOnlyIndicator.visible doesn't trigger relayout(?)
Item {
Layout.preferredHeight: 1
Layout.topMargin: -1
Layout.preferredWidth: watchOnlyIndicator.visible ? app.width : 1
}
}
}
@ -218,7 +221,9 @@ ApplicationWindow
id: mainStackView
width: parent.width
height: keyboardFreeZone.height - header.height
initialItem: Qt.resolvedUrl('WalletMainView.qml')
initialItem: Component {
WalletMainView {}
}
function getRoot() {
return mainStackView.get(0)
@ -454,7 +459,13 @@ ApplicationWindow
}
}
onClosing: {
onClosing: (close) => {
if (AppController.wantClose) {
// destroy most GUI components so that we don't dump so many null reference warnings on exit
app.header.visible = false
mainStackView.clear()
return
}
if (activeDialogs.length > 0) {
var activeDialog = activeDialogs[activeDialogs.length - 1]
if (activeDialog.allowClose) {
@ -469,22 +480,16 @@ ApplicationWindow
close.accepted = false
stack.pop()
} else {
// destroy most GUI components so that we don't dump so many null reference warnings on exit
if (app._wantClose) {
app.header.visible = false
mainStackView.clear()
} else {
var dialog = app.messageDialog.createObject(app, {
title: qsTr('Close Electrum?'),
yesno: true
})
dialog.accepted.connect(function() {
app._wantClose = true
app.close()
})
dialog.open()
close.accepted = false
}
var dialog = app.messageDialog.createObject(app, {
title: qsTr('Close Electrum?'),
yesno: true
})
dialog.accepted.connect(function() {
AppController.wantClose = true
app.close()
})
dialog.open()
close.accepted = false
}
}

2
electrum/gui/qml/qeaddressdetails.py

@ -1,4 +1,4 @@
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from electrum.logging import get_logger

8
electrum/gui/qml/qeaddresslistmodel.py

@ -1,7 +1,7 @@
from typing import TYPE_CHECKING, List
from PyQt5.QtCore import pyqtSlot, QSortFilterProxyModel, pyqtSignal, pyqtProperty
from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex
from PyQt6.QtCore import pyqtSlot, QSortFilterProxyModel, pyqtSignal, pyqtProperty
from PyQt6.QtCore import Qt, QAbstractListModel, QModelIndex
from electrum.logging import get_logger
from electrum.util import Satoshis
@ -107,7 +107,7 @@ class QEAddressCoinListModel(QAbstractListModel):
# define listmodel rolemap
_ROLE_NAMES=('type', 'addridx', 'address', 'label', 'balance', 'numtx', 'held', 'height', 'amount', 'outpoint',
'short_outpoint', 'short_id', 'txid')
_ROLE_KEYS = range(Qt.UserRole, Qt.UserRole + len(_ROLE_NAMES))
_ROLE_KEYS = range(Qt.ItemDataRole.UserRole, Qt.ItemDataRole.UserRole + len(_ROLE_NAMES))
_ROLE_MAP = dict(zip(_ROLE_KEYS, [bytearray(x.encode()) for x in _ROLE_NAMES]))
_ROLE_RMAP = dict(zip(_ROLE_NAMES, _ROLE_KEYS))
@ -128,7 +128,7 @@ class QEAddressCoinListModel(QAbstractListModel):
def data(self, index, role):
address = self._items[index.row()]
role_index = role - Qt.UserRole
role_index = role - Qt.ItemDataRole.UserRole
try:
value = address[self._ROLE_NAMES[role_index]]
except KeyError:

37
electrum/gui/qml/qeapp.py

@ -7,10 +7,10 @@ import html
import threading
from typing import TYPE_CHECKING, Set
from PyQt5.QtCore import (pyqtSlot, pyqtSignal, pyqtProperty, QObject,
from PyQt6.QtCore import (pyqtSlot, pyqtSignal, pyqtProperty, QObject,
qInstallMessageHandler, QTimer, QSortFilterProxyModel)
from PyQt5.QtGui import QGuiApplication, QFontDatabase
from PyQt5.QtQml import qmlRegisterType, qmlRegisterUncreatableType, QQmlApplicationEngine
from PyQt6.QtGui import QGuiApplication, QFontDatabase
from PyQt6.QtQml import qmlRegisterType, qmlRegisterUncreatableType, QQmlApplicationEngine
from electrum import version, constants
from electrum.i18n import _
@ -69,6 +69,7 @@ class QEAppController(BaseCrashReporter, QObject):
sendingBugreportSuccess = pyqtSignal(str)
sendingBugreportFailure = pyqtSignal(str)
secureWindowChanged = pyqtSignal()
wantCloseChanged = pyqtSignal()
def __init__(self, qeapp: 'ElectrumQmlApplication', qedaemon: 'QEDaemon', plugins: 'Plugins'):
BaseCrashReporter.__init__(self, None, None, None)
@ -100,6 +101,8 @@ class QEAppController(BaseCrashReporter, QObject):
if self.isAndroid():
self.bindIntent()
self._want_close = False
def on_wallet_loaded(self):
qewallet = self._qedaemon.currentWallet
if not qewallet:
@ -179,6 +182,16 @@ class QEAppController(BaseCrashReporter, QObject):
if self._intent:
self.on_new_intent(self._intent)
@pyqtProperty(bool, notify=wantCloseChanged)
def wantClose(self):
return self._want_close
@wantClose.setter
def wantClose(self, want_close):
if want_close != self._want_close:
self._want_close = want_close
self.wantCloseChanged.emit()
@pyqtSlot(str, str)
def doShare(self, data, title):
if not self.isAndroid():
@ -330,6 +343,13 @@ class ElectrumQmlApplication(QGuiApplication):
ElectrumQmlApplication._daemon = daemon
# TODO QT6 order of declaration is important now?
qmlRegisterType(QEAmount, 'org.electrum', 1, 0, 'Amount')
qmlRegisterType(QENewWalletWizard, 'org.electrum', 1, 0, 'QNewWalletWizard')
qmlRegisterType(QEServerConnectWizard, 'org.electrum', 1, 0, 'QServerConnectWizard')
qmlRegisterType(QEFilterProxyModel, 'org.electrum', 1, 0, 'FilterProxyModel')
qmlRegisterType(QSortFilterProxyModel, 'org.electrum', 1, 0, 'QSortFilterProxyModel')
qmlRegisterType(QEWallet, 'org.electrum', 1, 0, 'Wallet')
qmlRegisterType(QEBitcoin, 'org.electrum', 1, 0, 'Bitcoin')
qmlRegisterType(QEQRParser, 'org.electrum', 1, 0, 'QRParser')
@ -349,11 +369,12 @@ class ElectrumQmlApplication(QGuiApplication):
qmlRegisterType(QETxCanceller, 'org.electrum', 1, 0, 'TxCanceller')
qmlRegisterType(QEBip39RecoveryListModel, 'org.electrum', 1, 0, 'Bip39RecoveryListModel')
qmlRegisterUncreatableType(QEAmount, 'org.electrum', 1, 0, 'Amount', 'Amount can only be used as property')
qmlRegisterUncreatableType(QENewWalletWizard, 'org.electrum', 1, 0, 'QNewWalletWizard', 'QNewWalletWizard can only be used as property')
qmlRegisterUncreatableType(QEServerConnectWizard, 'org.electrum', 1, 0, 'QServerConnectWizard', 'QServerConnectWizard can only be used as property')
qmlRegisterUncreatableType(QEFilterProxyModel, 'org.electrum', 1, 0, 'FilterProxyModel', 'FilterProxyModel can only be used as property')
qmlRegisterUncreatableType(QSortFilterProxyModel, 'org.electrum', 1, 0, 'QSortFilterProxyModel', 'QSortFilterProxyModel can only be used as property')
# TODO QT6
# qmlRegisterUncreatableType(QEAmount, 'org.electrum', 1, 0, 'Amount', 'Amount can only be used as property')
# qmlRegisterUncreatableType(QENewWalletWizard, 'org.electrum', 1, 0, 'QNewWalletWizard', 'QNewWalletWizard can only be used as property')
# qmlRegisterUncreatableType(QEServerConnectWizard, 'org.electrum', 1, 0, 'QServerConnectWizard', 'QServerConnectWizard can only be used as property')
# qmlRegisterUncreatableType(QEFilterProxyModel, 'org.electrum', 1, 0, 'FilterProxyModel', 'FilterProxyModel can only be used as property')
# qmlRegisterUncreatableType(QSortFilterProxyModel, 'org.electrum', 1, 0, 'QSortFilterProxyModel', 'QSortFilterProxyModel can only be used as property')
self.engine = QQmlApplicationEngine(parent=self)

14
electrum/gui/qml/qebip39recovery.py

@ -1,8 +1,9 @@
import asyncio
import concurrent
from enum import IntEnum
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot
from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex, Q_ENUMS
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, pyqtEnum
from PyQt6.QtCore import Qt, QAbstractListModel, QModelIndex
from electrum import Network, keystore
from electrum.bip32 import BIP32Node
@ -15,21 +16,20 @@ from .util import TaskThread
class QEBip39RecoveryListModel(QAbstractListModel):
_logger = get_logger(__name__)
class State:
@pyqtEnum
class State(IntEnum):
Idle = -1
Scanning = 0
Success = 1
Failed = 2
Cancelled = 3
Q_ENUMS(State)
recoveryFailed = pyqtSignal()
stateChanged = pyqtSignal()
# define listmodel rolemap
_ROLE_NAMES=('description', 'derivation_path', 'script_type')
_ROLE_KEYS = range(Qt.UserRole, Qt.UserRole + len(_ROLE_NAMES))
_ROLE_KEYS = range(Qt.ItemDataRole.UserRole, Qt.ItemDataRole.UserRole + len(_ROLE_NAMES))
_ROLE_MAP = dict(zip(_ROLE_KEYS, [bytearray(x.encode()) for x in _ROLE_NAMES]))
def __init__(self, config, parent=None):
@ -47,7 +47,7 @@ class QEBip39RecoveryListModel(QAbstractListModel):
def data(self, index, role):
account = self._accounts[index.row()]
role_index = role - Qt.UserRole
role_index = role - Qt.ItemDataRole.UserRole
value = account[self._ROLE_NAMES[role_index]]
if isinstance(value, (bool, list, int, str)) or value is None:
return value

2
electrum/gui/qml/qebitcoin.py

@ -1,6 +1,6 @@
import asyncio
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from electrum import mnemonic
from electrum import keystore

8
electrum/gui/qml/qechanneldetails.py

@ -1,6 +1,7 @@
import threading
from enum import IntEnum
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, Q_ENUMS
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, pyqtEnum
from electrum.i18n import _
from electrum.gui import messages
@ -17,12 +18,11 @@ from .util import QtEventListener, event_listener
class QEChannelDetails(AuthMixin, QObject, QtEventListener):
_logger = get_logger(__name__)
class State: # subset, only ones we currently need in UI
@pyqtEnum
class State(IntEnum): # subset, only ones we currently need in UI
Closed = ChannelState.CLOSED
Redeemed = ChannelState.REDEEMED
Q_ENUMS(State)
channelChanged = pyqtSignal()
channelCloseSuccess = pyqtSignal()
channelCloseFailed = pyqtSignal([str], arguments=['message'])

8
electrum/gui/qml/qechannellistmodel.py

@ -1,5 +1,5 @@
from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot
from PyQt6.QtCore import Qt, QAbstractListModel, QModelIndex
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot
from electrum.lnchannel import ChannelState
from electrum.lnutil import LOCAL, REMOTE
@ -20,7 +20,7 @@ class QEChannelListModel(QAbstractListModel, QtEventListener):
'can_receive', 'l_csv_delay', 'r_csv_delay', 'send_frozen', 'receive_frozen',
'type', 'node_id', 'node_alias', 'short_cid', 'funding_tx', 'is_trampoline',
'is_backup', 'is_imported', 'local_capacity', 'remote_capacity')
_ROLE_KEYS = range(Qt.UserRole, Qt.UserRole + len(_ROLE_NAMES))
_ROLE_KEYS = range(Qt.ItemDataRole.UserRole, Qt.ItemDataRole.UserRole + len(_ROLE_NAMES))
_ROLE_MAP = dict(zip(_ROLE_KEYS, [bytearray(x.encode()) for x in _ROLE_NAMES]))
_ROLE_RMAP = dict(zip(_ROLE_NAMES, _ROLE_KEYS))
@ -70,7 +70,7 @@ class QEChannelListModel(QAbstractListModel, QtEventListener):
def data(self, index, role):
tx = self._channels[index.row()]
role_index = role - Qt.UserRole
role_index = role - Qt.ItemDataRole.UserRole
value = tx[self._ROLE_NAMES[role_index]]
if isinstance(value, (bool, list, int, str, QEAmount)) or value is None:
return value

2
electrum/gui/qml/qechannelopener.py

@ -3,7 +3,7 @@ from concurrent.futures import CancelledError
from asyncio.exceptions import TimeoutError
from typing import TYPE_CHECKING, Optional
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from electrum.i18n import _
from electrum.gui import messages

2
electrum/gui/qml/qeconfig.py

@ -2,7 +2,7 @@ import copy
from decimal import Decimal
from typing import TYPE_CHECKING
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QRegularExpression
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QRegularExpression
from electrum.bitcoin import TOTAL_COIN_SUPPLY_LIMIT_IN_BTC
from electrum.i18n import set_language, languages

8
electrum/gui/qml/qedaemon.py

@ -3,8 +3,8 @@ import os
import threading
from typing import TYPE_CHECKING
from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from PyQt6.QtCore import Qt, QAbstractListModel, QModelIndex
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from electrum.i18n import _
from electrum.logging import get_logger
@ -32,7 +32,7 @@ class QEWalletListModel(QAbstractListModel):
# define listmodel rolemap
_ROLE_NAMES= ('name', 'path', 'active')
_ROLE_KEYS = range(Qt.UserRole, Qt.UserRole + len(_ROLE_NAMES))
_ROLE_KEYS = range(Qt.ItemDataRole.UserRole, Qt.ItemDataRole.UserRole + len(_ROLE_NAMES))
_ROLE_MAP = dict(zip(_ROLE_KEYS, [bytearray(x.encode()) for x in _ROLE_NAMES]))
def __init__(self, daemon, parent=None):
@ -49,7 +49,7 @@ class QEWalletListModel(QAbstractListModel):
def data(self, index, role):
(wallet_name, wallet_path) = self._wallets[index.row()]
role_index = role - Qt.UserRole
role_index = role - Qt.ItemDataRole.UserRole
role_name = self._ROLE_NAMES[role_index]
if role_name == 'name':
return wallet_name

2
electrum/gui/qml/qefx.py

@ -1,7 +1,7 @@
from datetime import datetime
from decimal import Decimal
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QRegularExpression
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QRegularExpression
from electrum.bitcoin import COIN
from electrum.exchange_rate import FxThread

12
electrum/gui/qml/qeinvoice.py

@ -1,7 +1,8 @@
from enum import IntEnum
from typing import Optional, Dict, Any
from urllib.parse import urlparse
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, Q_ENUMS, QTimer
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, pyqtEnum, QTimer
from electrum.i18n import _
from electrum.logging import get_logger
@ -18,13 +19,15 @@ from .util import status_update_timer_interval, QtEventListener, event_listener
class QEInvoice(QObject, QtEventListener):
class Type:
@pyqtEnum
class Type(IntEnum):
Invalid = -1
OnchainInvoice = 0
LightningInvoice = 1
LNURLPayRequest = 2
class Status:
@pyqtEnum
class Status(IntEnum):
Unpaid = PR_UNPAID
Expired = PR_EXPIRED
Unknown = PR_UNKNOWN
@ -34,9 +37,6 @@ class QEInvoice(QObject, QtEventListener):
Routing = PR_ROUTING
Unconfirmed = PR_UNCONFIRMED
Q_ENUMS(Type)
Q_ENUMS(Status)
_logger = get_logger(__name__)
invoiceChanged = pyqtSignal()

8
electrum/gui/qml/qeinvoicelistmodel.py

@ -1,8 +1,8 @@
from abc import abstractmethod
from typing import TYPE_CHECKING, List, Dict, Any
from PyQt5.QtCore import pyqtSlot, QTimer
from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex
from PyQt6.QtCore import pyqtSlot, QTimer
from PyQt6.QtCore import Qt, QAbstractListModel, QModelIndex
from electrum.logging import get_logger
from electrum.util import Satoshis, format_time
@ -22,7 +22,7 @@ class QEAbstractInvoiceListModel(QAbstractListModel):
_ROLE_NAMES=('key', 'is_lightning', 'timestamp', 'date', 'message', 'amount',
'status', 'status_str', 'address', 'expiry', 'type', 'onchain_fallback',
'lightning_invoice')
_ROLE_KEYS = range(Qt.UserRole, Qt.UserRole + len(_ROLE_NAMES))
_ROLE_KEYS = range(Qt.ItemDataRole.UserRole, Qt.ItemDataRole.UserRole + len(_ROLE_NAMES))
_ROLE_MAP = dict(zip(_ROLE_KEYS, [bytearray(x.encode()) for x in _ROLE_NAMES]))
_ROLE_RMAP = dict(zip(_ROLE_NAMES, _ROLE_KEYS))
@ -49,7 +49,7 @@ class QEAbstractInvoiceListModel(QAbstractListModel):
def data(self, index, role):
invoice = self._invoices[index.row()]
role_index = role - Qt.UserRole
role_index = role - Qt.ItemDataRole.UserRole
value = invoice[self._ROLE_NAMES[role_index]]
if isinstance(value, (bool, list, int, str, QEAmount)) or value is None:

2
electrum/gui/qml/qelnpaymentdetails.py

@ -1,4 +1,4 @@
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from electrum.logging import get_logger
from electrum.util import bfh, format_time

2
electrum/gui/qml/qemodelfilter.py

@ -1,4 +1,4 @@
from PyQt5.QtCore import pyqtSignal, pyqtProperty, QSortFilterProxyModel, QModelIndex, pyqtSlot
from PyQt6.QtCore import pyqtSignal, pyqtProperty, QSortFilterProxyModel, QModelIndex, pyqtSlot
from electrum.logging import get_logger

2
electrum/gui/qml/qenetwork.py

@ -1,6 +1,6 @@
from typing import TYPE_CHECKING
from PyQt5.QtCore import pyqtProperty, pyqtSignal, QObject
from PyQt6.QtCore import pyqtProperty, pyqtSignal, QObject
from electrum.logging import get_logger
from electrum import constants

8
electrum/gui/qml/qeqr.py

@ -7,9 +7,9 @@ import urllib
from PIL import Image, ImageQt
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QRect, QPoint
from PyQt5.QtGui import QImage, QColor
from PyQt5.QtQuick import QQuickImageProvider
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QRect, QPoint
from PyQt6.QtGui import QImage, QColor
from PyQt6.QtQuick import QQuickImageProvider
from electrum.logging import get_logger
from electrum.qrreader import get_qr_reader
@ -123,7 +123,7 @@ class QEQRParser(QObject):
class QEQRImageProvider(QQuickImageProvider):
def __init__(self, max_size, parent=None):
super().__init__(QQuickImageProvider.Image)
super().__init__(QQuickImageProvider.ImageType.Image)
self._max_size = max_size
self.qimg = None

8
electrum/gui/qml/qerequestdetails.py

@ -1,6 +1,7 @@
from enum import IntEnum
from typing import Optional
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QTimer, Q_ENUMS
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QTimer, pyqtEnum
from electrum.logging import get_logger
from electrum.invoices import (PR_UNPAID, PR_EXPIRED, PR_UNKNOWN, PR_PAID, PR_INFLIGHT,
@ -13,7 +14,8 @@ from .util import QtEventListener, event_listener, status_update_timer_interval
class QERequestDetails(QObject, QtEventListener):
class Status:
@pyqtEnum
class Status(IntEnum):
Unpaid = PR_UNPAID
Expired = PR_EXPIRED
Unknown = PR_UNKNOWN
@ -23,8 +25,6 @@ class QERequestDetails(QObject, QtEventListener):
Routing = PR_ROUTING
Unconfirmed = PR_UNCONFIRMED
Q_ENUMS(Status)
_logger = get_logger(__name__)
detailsChanged = pyqtSignal() # generic request properties changed signal

8
electrum/gui/qml/qeserverlistmodel.py

@ -1,5 +1,5 @@
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot
from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot
from PyQt6.QtCore import Qt, QAbstractListModel, QModelIndex
from electrum.logging import get_logger
from electrum.util import Satoshis
@ -14,7 +14,7 @@ class QEServerListModel(QAbstractListModel, QtEventListener):
# define listmodel rolemap
_ROLE_NAMES=('name', 'address', 'is_connected', 'is_primary', 'is_tor', 'chain', 'height')
_ROLE_KEYS = range(Qt.UserRole, Qt.UserRole + len(_ROLE_NAMES))
_ROLE_KEYS = range(Qt.ItemDataRole.UserRole, Qt.ItemDataRole.UserRole + len(_ROLE_NAMES))
_ROLE_MAP = dict(zip(_ROLE_KEYS, [bytearray(x.encode()) for x in _ROLE_NAMES]))
_ROLE_RMAP = dict(zip(_ROLE_NAMES, _ROLE_KEYS))
@ -52,7 +52,7 @@ class QEServerListModel(QAbstractListModel, QtEventListener):
def data(self, index, role):
server = self._servers[index.row()]
role_index = role - Qt.UserRole
role_index = role - Qt.ItemDataRole.UserRole
value = server[self._ROLE_NAMES[role_index]]
if isinstance(value, (bool, list, int, str)) or value is None:

8
electrum/gui/qml/qeswaphelper.py

@ -1,9 +1,10 @@
import asyncio
import concurrent
import threading
from enum import IntEnum
from typing import Union
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QTimer, Q_ENUMS
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QTimer, pyqtEnum
from electrum.i18n import _
from electrum.bitcoin import DummyAddress
@ -23,7 +24,8 @@ class InvalidSwapParameters(Exception): pass
class QESwapHelper(AuthMixin, QObject, QtEventListener):
_logger = get_logger(__name__)
class State:
@pyqtEnum
class State(IntEnum):
Initialized = 0
ServiceReady = 1
Started = 2
@ -31,8 +33,6 @@ class QESwapHelper(AuthMixin, QObject, QtEventListener):
Success = 4
Cancelled = 5
Q_ENUMS(State)
confirm = pyqtSignal([str], arguments=['message'])
error = pyqtSignal([str], arguments=['message'])

8
electrum/gui/qml/qetransactionlistmodel.py

@ -1,8 +1,8 @@
from datetime import datetime, timedelta
from typing import TYPE_CHECKING, Dict, Any
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot
from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot
from PyQt6.QtCore import Qt, QAbstractListModel, QModelIndex
from electrum.logging import get_logger
from electrum.util import Satoshis, TxMinedInfo
@ -22,7 +22,7 @@ class QETransactionListModel(QAbstractListModel, QtEventListener):
_ROLE_NAMES=('txid', 'fee_sat', 'height', 'confirmations', 'timestamp', 'monotonic_timestamp',
'incoming', 'value', 'date', 'label', 'txpos_in_block', 'fee',
'inputs', 'outputs', 'section', 'type', 'lightning', 'payment_hash', 'key', 'complete')
_ROLE_KEYS = range(Qt.UserRole, Qt.UserRole + len(_ROLE_NAMES))
_ROLE_KEYS = range(Qt.ItemDataRole.UserRole, Qt.ItemDataRole.UserRole + len(_ROLE_NAMES))
_ROLE_MAP = dict(zip(_ROLE_KEYS, [bytearray(x.encode()) for x in _ROLE_NAMES]))
_ROLE_RMAP = dict(zip(_ROLE_NAMES, _ROLE_KEYS))
@ -95,7 +95,7 @@ class QETransactionListModel(QAbstractListModel, QtEventListener):
def data(self, index, role):
tx = self.tx_history[index.row()]
role_index = role - Qt.UserRole
role_index = role - Qt.ItemDataRole.UserRole
try:
value = tx[self._ROLE_NAMES[role_index]]

2
electrum/gui/qml/qetxdetails.py

@ -1,6 +1,6 @@
from typing import Optional
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from electrum.i18n import _
from electrum.logging import get_logger

2
electrum/gui/qml/qetxfinalizer.py

@ -2,7 +2,7 @@ from decimal import Decimal
from typing import Optional, TYPE_CHECKING
from functools import partial
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from electrum.logging import get_logger
from electrum.i18n import _

2
electrum/gui/qml/qetypes.py

@ -1,4 +1,4 @@
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from electrum.logging import get_logger
from electrum.i18n import _

2
electrum/gui/qml/qewallet.py

@ -6,7 +6,7 @@ import time
from typing import TYPE_CHECKING, Callable
from functools import partial
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QTimer
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QTimer
from electrum.i18n import _
from electrum.invoices import InvoiceError, PR_PAID, PR_BROADCASTING, PR_BROADCAST

2
electrum/gui/qml/qewizard.py

@ -1,7 +1,7 @@
import os
from typing import TYPE_CHECKING
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from electrum.logging import get_logger
from electrum import mnemonic

2
electrum/gui/qml/util.py

@ -5,7 +5,7 @@ from functools import wraps
from time import time
from typing import Callable, Optional, NamedTuple
from PyQt5.QtCore import pyqtSignal, QThread
from PyQt6.QtCore import pyqtSignal, QThread
from electrum.logging import Logger
from electrum.util import EventListener, event_listener

2
electrum/plugins/labels/qml.py

@ -1,6 +1,6 @@
import threading
from PyQt5.QtCore import pyqtSignal, pyqtSlot
from PyQt6.QtCore import pyqtSignal, pyqtSlot
from electrum.i18n import _
from electrum.plugin import hook

2
electrum/plugins/trustedcoin/common_qt.py

@ -3,7 +3,7 @@ import socket
import base64
from typing import TYPE_CHECKING
from PyQt5.QtCore import pyqtSignal, pyqtProperty, pyqtSlot
from PyQt6.QtCore import pyqtSignal, pyqtProperty, pyqtSlot # TODO: common code, Qt5/Qt6 mismatch!
from electrum.i18n import _
from electrum.bip32 import BIP32Node

1
electrum/plugins/trustedcoin/qml.py

@ -15,6 +15,7 @@ if TYPE_CHECKING:
from electrum.wizard import NewWalletWizard
class Plugin(TrustedCoinPlugin):
def __init__(self, *args):

Loading…
Cancel
Save