Browse Source

Qt: add JMFileDialog with async/open usage

add_frost_channel_encryption
zebra-lucky 2 months ago
parent
commit
971f6c87d7
  1. 136
      scripts/joinmarket-qt.py

136
scripts/joinmarket-qt.py

@ -114,6 +114,21 @@ log.addHandler(handler)
from jmqtui import Ui_OpenWalletDialog from jmqtui import Ui_OpenWalletDialog
class JMFileDialog(QFileDialog):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.result_fut = asyncio.get_event_loop().create_future()
@QtCore.Slot(QMessageBox.StandardButton)
def on_finished(self, result):
self.result_fut.set_result(result)
async def result(self):
await self.result_fut
return self.result_fut.result()
class JMOpenWalletDialog(QDialog, Ui_OpenWalletDialog): class JMOpenWalletDialog(QDialog, Ui_OpenWalletDialog):
DEFAULT_WALLET_FILE_TEXT = "wallet.jmdat" DEFAULT_WALLET_FILE_TEXT = "wallet.jmdat"
@ -124,19 +139,27 @@ class JMOpenWalletDialog(QDialog, Ui_OpenWalletDialog):
self.setupUi(self) self.setupUi(self)
self.errorMessageLabel.setWordWrap(True); self.errorMessageLabel.setWordWrap(True);
self.passphraseEdit.setFocus() self.passphraseEdit.setFocus()
self.chooseWalletButton.clicked.connect(self.chooseWalletFile) self.chooseWalletButton.clicked.connect(lambda:
asyncio.ensure_future(self.chooseWalletFile()))
def chooseWalletFile(self, error_text: str = ""):
(filename, _) = QFileDialog.getOpenFileName( async def chooseWalletFile(self, error_text: str = ""):
self, d = JMFileDialog(self)
"Choose Wallet File", d.setOptions(QFileDialog.DontUseNativeDialog)
self._get_wallets_path(), d.setWindowTitle('Choose Wallet File')
options=QFileDialog.DontUseNativeDialog, d.setDirectory(self._get_wallets_path())
) d.finished.connect(d.on_finished)
if filename: d.open()
self.walletFileEdit.setText(filename) await d.result_fut
self.passphraseEdit.setFocus() result = d.result_fut.result()
self.errorMessageLabel.setText(self.verify_lock(filename)) if result != QDialog.Accepted:
return
filenames = d.selectedFiles()
if not filenames or len(filenames) != 1:
return
filename = filenames[0]
self.walletFileEdit.setText(os.path.basename(filename))
self.passphraseEdit.setFocus()
self.errorMessageLabel.setText(self.verify_lock(filename))
@staticmethod @staticmethod
def _get_wallets_path() -> str: def _get_wallets_path() -> str:
@ -486,21 +509,31 @@ class SpendTab(QWidget):
return return
self.sch_startButton.setEnabled(True) self.sch_startButton.setEnabled(True)
def selectSchedule(self): async def selectSchedule(self):
current_path = os.path.dirname(os.path.realpath(__file__)) current_path = os.path.dirname(
firstarg = QFileDialog.getOpenFileName(self, os.path.dirname(os.path.realpath(__file__)))
'Choose Schedule File', d = JMFileDialog(self)
dir=current_path, d.setOptions(QFileDialog.DontUseNativeDialog)
options=QFileDialog.DontUseNativeDialog) d.setWindowTitle('Choose Schedule File')
#TODO validate the schedule d.setDirectory(current_path)
log.debug('Looking for schedule in: ' + str(firstarg)) d.finished.connect(d.on_finished)
if not firstarg: d.open()
await d.result_fut
result = d.result_fut.result()
if result != QDialog.Accepted:
return
filenames = d.selectedFiles()
if not filenames or len(filenames) != 1:
return return
filename = filenames[0]
# TODO validate the schedule
log.debug('Looking for schedule in: ' + str(filename))
#extract raw text before processing #extract raw text before processing
with open(firstarg[0], 'rb') as f: with open(filename, 'rb') as f:
rawsched = f.read() rawsched = f.read()
res, schedule = get_schedule(firstarg[0]) res, schedule = get_schedule(filename)
if not res: if not res:
asyncio.ensure_future( asyncio.ensure_future(
JMQtMessageBox( JMQtMessageBox(
@ -509,7 +542,7 @@ class SpendTab(QWidget):
else: else:
mainWindow.statusBar().showMessage("Schedule loaded OK.") mainWindow.statusBar().showMessage("Schedule loaded OK.")
self.spendstate.loaded_schedule = schedule self.spendstate.loaded_schedule = schedule
self.spendstate.schedule_name = os.path.basename(str(firstarg[0])) self.spendstate.schedule_name = os.path.basename(filename)
self.updateSchedView() self.updateSchedView()
if self.spendstate.schedule_name == "TUMBLE.schedule": if self.spendstate.schedule_name == "TUMBLE.schedule":
@ -596,7 +629,8 @@ class SpendTab(QWidget):
current_schedule_layout.addWidget(self.sched_view) current_schedule_layout.addWidget(self.sched_view)
sch_layout.addLayout(current_schedule_layout, 0, 0, 1, 1) sch_layout.addLayout(current_schedule_layout, 0, 0, 1, 1)
self.schedule_set_button = QPushButton('Choose schedule file') self.schedule_set_button = QPushButton('Choose schedule file')
self.schedule_set_button.clicked.connect(self.selectSchedule) self.schedule_set_button.clicked.connect(
lambda: asyncio.ensure_future(self.selectSchedule()))
self.schedule_generate_button = QPushButton('Generate tumble schedule') self.schedule_generate_button = QPushButton('Generate tumble schedule')
self.schedule_generate_button.clicked.connect( self.schedule_generate_button.clicked.connect(
lambda: asyncio.ensure_future(self.generateTumbleSchedule())) lambda: asyncio.ensure_future(self.generateTumbleSchedule()))
@ -2148,14 +2182,22 @@ class JMMainWindow(QMainWindow):
if jm_single().config.get("BLOCKCHAIN", "blockchain_source") != "regtest": if jm_single().config.get("BLOCKCHAIN", "blockchain_source") != "regtest":
# guaranteed to exist as load_program_config was called on startup: # guaranteed to exist as load_program_config was called on startup:
wallets_path = os.path.join(jm_single().datadir, 'wallets') wallets_path = os.path.join(jm_single().datadir, 'wallets')
firstarg = QFileDialog.getOpenFileName(self, d = JMFileDialog(self)
'Choose Wallet File', d.setOptions(QFileDialog.DontUseNativeDialog)
wallets_path, d.setWindowTitle('Choose Wallet File')
options=QFileDialog.DontUseNativeDialog) d.setDirectory(wallets_path)
#TODO validate the file looks vaguely like a wallet file d.finished.connect(d.on_finished)
log.debug('Looking for wallet in: ' + str(firstarg)) d.open()
if not firstarg or not firstarg[0]: await d.result_fut
result = d.result_fut.result()
if result != QDialog.Accepted:
return return
filenames = d.selectedFiles()
if not filenames or len(filenames) != 1:
return
filename = filenames[0]
#TODO validate the file looks vaguely like a wallet file
log.debug('Looking for wallet in: ' + str(filename))
decrypted = False decrypted = False
while not decrypted: while not decrypted:
text, ok = QInputDialog.getText(self, text, ok = QInputDialog.getText(self,
@ -2167,7 +2209,7 @@ class JMMainWindow(QMainWindow):
pwd = str(text).strip() pwd = str(text).strip()
try: try:
decrypted = await self.loadWalletFromBlockchain( decrypted = await self.loadWalletFromBlockchain(
firstarg[0], pwd) filename, pwd)
except Exception as e: except Exception as e:
await JMQtMessageBox(self, str(e), await JMQtMessageBox(self, str(e),
mbtype='warn', title="Error") mbtype='warn', title="Error")
@ -2182,20 +2224,23 @@ class JMMainWindow(QMainWindow):
'Load Testnet wallet', 'Load Testnet wallet',
'Enter a testnet seed:', 'Enter a testnet seed:',
QLineEdit.Normal) QLineEdit.Normal)
if not ok: testnet_seed = testnet_seed.strip()
if not ok or not testnet_seed:
await JMQtMessageBox(self, "No seed entered, aborting",
mbtype='warn', title="Error")
return return
firstarg = str(testnet_seed) filename = testnet_seed
pwd = None pwd = None
#ignore return value as there is no decryption failure possible #ignore return value as there is no decryption failure possible
await self.loadWalletFromBlockchain(firstarg, pwd) await self.loadWalletFromBlockchain(filename, pwd)
async def loadWalletFromBlockchain(self, firstarg=None, async def loadWalletFromBlockchain(self, filename=None,
pwd=None, rethrow=False): pwd=None, rethrow=False):
if firstarg: if filename:
wallet_path = get_wallet_path(str(firstarg), None) wallet_path = get_wallet_path(str(filename), None)
try: try:
wallet = await open_test_wallet_maybe( wallet = await open_test_wallet_maybe(
wallet_path, str(firstarg), None, ask_for_password=False, wallet_path, str(filename), None, ask_for_password=False,
password=pwd.encode('utf-8') if pwd else None, password=pwd.encode('utf-8') if pwd else None,
gap_limit=jm_single().config.getint("GUI", "gaplimit")) gap_limit=jm_single().config.getint("GUI", "gaplimit"))
except RetryableStorageError as e: except RetryableStorageError as e:
@ -2206,7 +2251,7 @@ class JMMainWindow(QMainWindow):
mbtype='warn', title="Error") mbtype='warn', title="Error")
return False return False
# only used for GUI display on regtest: # only used for GUI display on regtest:
self.testwalletname = wallet.seed = str(firstarg) self.testwalletname = wallet.seed = str(filename)
if 'listunspent_args' not in jm_single().config.options('POLICY'): if 'listunspent_args' not in jm_single().config.options('POLICY'):
jm_single().config.set('POLICY', 'listunspent_args', '[0]') jm_single().config.set('POLICY', 'listunspent_args', '[0]')
assert wallet, "No wallet loaded" assert wallet, "No wallet loaded"
@ -2293,7 +2338,8 @@ class JMMainWindow(QMainWindow):
log.debug('generating wallet') log.debug('generating wallet')
if jm_single().config.get("BLOCKCHAIN", "blockchain_source") == "regtest": if jm_single().config.get("BLOCKCHAIN", "blockchain_source") == "regtest":
seed = await self.getTestnetSeed() seed = await self.getTestnetSeed()
await self.selectWallet(testnet_seed=seed) if seed:
await self.selectWallet(testnet_seed=seed)
else: else:
await self.initWallet() await self.initWallet()
@ -2334,11 +2380,12 @@ class JMMainWindow(QMainWindow):
async def getTestnetSeed(self): async def getTestnetSeed(self):
text, ok = QInputDialog.getText( text, ok = QInputDialog.getText(
self, 'Testnet seed', 'Enter a 32 char hex string as seed:') self, 'Testnet seed', 'Enter a 32 char hex string as seed:')
text = text.strip()
if not ok or not text: if not ok or not text:
await JMQtMessageBox(self, "No seed entered, aborting", await JMQtMessageBox(self, "No seed entered, aborting",
mbtype='warn', title="Error") mbtype='warn', title="Error")
return return
return str(text).strip() return text
def showSeedDialog(self): def showSeedDialog(self):
if not self.wallet_service: if not self.wallet_service:
@ -2440,6 +2487,7 @@ class JMMainWindow(QMainWindow):
await self.loadWalletFromBlockchain( await self.loadWalletFromBlockchain(
self.walletname, pwd=self.textpassword) self.walletname, pwd=self.textpassword)
async def get_wallet_printout(wallet_service): async def get_wallet_printout(wallet_service):
"""Given a WalletService object, retrieve the list of """Given a WalletService object, retrieve the list of
addresses and corresponding balances to be displayed. addresses and corresponding balances to be displayed.

Loading…
Cancel
Save