Browse Source

Qt settings_dialog: use signals

- changes must apply to all windows
 - do not keep reference to the window object
patch-4
ThomasV 3 years ago
parent
commit
fdee31af05
  1. 16
      electrum/contacts.py
  2. 5
      electrum/gui/qt/__init__.py
  3. 31
      electrum/gui/qt/main_window.py
  4. 82
      electrum/gui/qt/settings_dialog.py

16
electrum/contacts.py

@ -21,15 +21,15 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
import re import re
import dns import dns
import threading
from dns.exception import DNSException from dns.exception import DNSException
from . import bitcoin from . import bitcoin
from . import dnssec from . import dnssec
from .util import read_json_file, write_json_file, to_string from .util import read_json_file, write_json_file, to_string
from .logging import Logger from .logging import Logger
from .util import trigger_callback
class Contacts(dict, Logger): class Contacts(dict, Logger):
@ -94,6 +94,18 @@ class Contacts(dict, Logger):
} }
raise Exception("Invalid Bitcoin address or alias", k) raise Exception("Invalid Bitcoin address or alias", k)
def fetch_openalias(self, config):
self.alias_info = None
alias = config.get('alias')
if alias:
alias = str(alias)
def f():
self.alias_info = self.resolve_openalias(alias)
trigger_callback('alias_received')
t = threading.Thread(target=f)
t.setDaemon(True)
t.start()
def resolve_openalias(self, url): def resolve_openalias(self, url):
# support email-style addresses, per the OA standard # support email-style addresses, per the OA standard
url = url.replace('@', '.') url = url.replace('@', '.')

5
electrum/gui/qt/__init__.py

@ -95,6 +95,11 @@ class OpenFileEventFilter(QObject):
class QElectrumApplication(QApplication): class QElectrumApplication(QApplication):
new_window_signal = pyqtSignal(str, object) new_window_signal = pyqtSignal(str, object)
quit_signal = pyqtSignal() quit_signal = pyqtSignal()
refresh_tabs_signal = pyqtSignal()
refresh_amount_edits_signal = pyqtSignal()
update_status_signal = pyqtSignal()
update_fiat_signal = pyqtSignal()
alias_received_signal = pyqtSignal()
class QNetworkUpdatedSignalObject(QObject): class QNetworkUpdatedSignalObject(QObject):

31
electrum/gui/qt/main_window.py

@ -170,7 +170,6 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
payment_request_error_signal = pyqtSignal() payment_request_error_signal = pyqtSignal()
network_signal = pyqtSignal(str, object) network_signal = pyqtSignal(str, object)
#ln_payment_attempt_signal = pyqtSignal(str) #ln_payment_attempt_signal = pyqtSignal(str)
alias_received_signal = pyqtSignal()
computing_privkeys_signal = pyqtSignal() computing_privkeys_signal = pyqtSignal()
show_privkeys_signal = pyqtSignal() show_privkeys_signal = pyqtSignal()
show_error_signal = pyqtSignal(str) show_error_signal = pyqtSignal(str)
@ -274,6 +273,11 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
for i in range(wrtabs.count()): for i in range(wrtabs.count()):
QShortcut(QKeySequence("Alt+" + str(i + 1)), self, lambda i=i: wrtabs.setCurrentIndex(i)) QShortcut(QKeySequence("Alt+" + str(i + 1)), self, lambda i=i: wrtabs.setCurrentIndex(i))
self.app.refresh_tabs_signal.connect(self.refresh_tabs)
self.app.refresh_amount_edits_signal.connect(self.refresh_amount_edits)
self.app.update_status_signal.connect(self.update_status)
self.app.update_fiat_signal.connect(self.update_fiat)
self.payment_request_ok_signal.connect(self.payment_request_ok) self.payment_request_ok_signal.connect(self.payment_request_ok)
self.payment_request_error_signal.connect(self.payment_request_error) self.payment_request_error_signal.connect(self.payment_request_error)
self.show_error_signal.connect(self.show_error) self.show_error_signal.connect(self.show_error)
@ -301,7 +305,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
#self.fee_slider.update() #self.fee_slider.update()
self.load_wallet(wallet) self.load_wallet(wallet)
gui_object.timer.timeout.connect(self.timer_actions) gui_object.timer.timeout.connect(self.timer_actions)
self.fetch_alias() self.contacts.fetch_openalias(self.config)
# If the option hasn't been set yet # If the option hasn't been set yet
if config.get('check_updates') is None: if config.get('check_updates') is None:
@ -496,18 +500,6 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
else: else:
self.logger.info(f"unexpected network event: {event} {args}") self.logger.info(f"unexpected network event: {event} {args}")
def fetch_alias(self):
self.alias_info = None
alias = self.config.get('alias')
if alias:
alias = str(alias)
def f():
self.alias_info = self.contacts.resolve_openalias(alias)
self.alias_received_signal.emit()
t = threading.Thread(target=f)
t.setDaemon(True)
t.start()
def close_wallet(self): def close_wallet(self):
if self.wallet: if self.wallet:
self.logger.info(f'close_wallet {self.wallet.storage.path}') self.logger.info(f'close_wallet {self.wallet.storage.path}')
@ -3348,21 +3340,26 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
header_layout.addWidget(InfoButton(WIF_HELP_TEXT), alignment=Qt.AlignRight) header_layout.addWidget(InfoButton(WIF_HELP_TEXT), alignment=Qt.AlignRight)
self._do_import(title, header_layout, lambda x: self.wallet.import_private_keys(x, password)) self._do_import(title, header_layout, lambda x: self.wallet.import_private_keys(x, password))
def refresh_amount_edits(self):
edits = self.amount_e, self.receive_amount_e
amounts = [edit.get_amount() for edit in edits]
for edit, amount in zip(edits, amounts):
edit.setAmount(amount)
def update_fiat(self): def update_fiat(self):
b = self.fx and self.fx.is_enabled() b = self.fx and self.fx.is_enabled()
self.fiat_send_e.setVisible(b) self.fiat_send_e.setVisible(b)
self.fiat_receive_e.setVisible(b) self.fiat_receive_e.setVisible(b)
self.history_model.refresh('update_fiat')
self.history_list.update() self.history_list.update()
self.address_list.refresh_headers() self.address_list.refresh_headers()
self.address_list.refresh_all() self.address_list.update()
self.update_status() self.update_status()
def settings_dialog(self): def settings_dialog(self):
from .settings_dialog import SettingsDialog from .settings_dialog import SettingsDialog
d = SettingsDialog(self, self.config) d = SettingsDialog(self, self.config)
self.alias_received_signal.connect(d.set_alias_color)
d.exec_() d.exec_()
self.alias_received_signal.disconnect(d.set_alias_color)
if self.fx: if self.fx:
self.fx.trigger_update() self.fx.trigger_update()
run_hook('close_settings_dialog') run_hook('close_settings_dialog')

82
electrum/gui/qt/settings_dialog.py

@ -27,7 +27,7 @@ import ast
from typing import Optional, TYPE_CHECKING from typing import Optional, TYPE_CHECKING
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QComboBox, QTabWidget, from PyQt5.QtWidgets import (QComboBox, QTabWidget, QDialog,
QSpinBox, QFileDialog, QCheckBox, QLabel, QSpinBox, QFileDialog, QCheckBox, QLabel,
QVBoxLayout, QGridLayout, QLineEdit, QVBoxLayout, QGridLayout, QLineEdit,
QPushButton, QWidget, QHBoxLayout) QPushButton, QWidget, QHBoxLayout)
@ -47,16 +47,22 @@ if TYPE_CHECKING:
from .main_window import ElectrumWindow from .main_window import ElectrumWindow
class SettingsDialog(WindowModalDialog): class SettingsDialog(QDialog):
def __init__(self, parent: 'ElectrumWindow', config: 'SimpleConfig'): def __init__(self, window: 'ElectrumWindow', config: 'SimpleConfig'):
WindowModalDialog.__init__(self, parent, _('Preferences')) QDialog.__init__(self)
self.setWindowTitle(_('Preferences'))
self.setMinimumWidth(500)
self.config = config self.config = config
self.window = parent self.network = window.network
self.app = window.app
self.need_restart = False self.need_restart = False
self.fx = self.window.fx self.fx = window.fx
self.wallet = self.window.wallet self.wallet = window.wallet
util.register_callback(self.on_network_callback, ['alias_received'])
self.app.alias_received_signal.connect(self.set_alias_color)
vbox = QVBoxLayout() vbox = QVBoxLayout()
tabs = QTabWidget() tabs = QTabWidget()
@ -94,7 +100,7 @@ class SettingsDialog(WindowModalDialog):
if self.config.num_zeros != value: if self.config.num_zeros != value:
self.config.num_zeros = value self.config.num_zeros = value
self.config.set_key('num_zeros', value, True) self.config.set_key('num_zeros', value, True)
self.window.refresh_tabs() self.app.refresh_tabs_signal.emit()
nz.valueChanged.connect(on_nz) nz.valueChanged.connect(on_nz)
# invoices # invoices
@ -153,10 +159,10 @@ class SettingsDialog(WindowModalDialog):
use_gossip = not bool(use_trampoline) use_gossip = not bool(use_trampoline)
self.config.set_key('use_gossip', use_gossip) self.config.set_key('use_gossip', use_gossip)
if use_gossip: if use_gossip:
self.window.network.start_gossip() self.network.start_gossip()
else: else:
self.window.network.run_from_another_thread( self.network.run_from_another_thread(
self.window.network.stop_gossip()) self.network.stop_gossip())
util.trigger_callback('ln_gossip_sync_progress') util.trigger_callback('ln_gossip_sync_progress')
# FIXME: update all wallet windows # FIXME: update all wallet windows
util.trigger_callback('channels_updated', self.wallet) util.trigger_callback('channels_updated', self.wallet)
@ -210,7 +216,7 @@ class SettingsDialog(WindowModalDialog):
if self.config.amt_precision_post_satoshi != prec: if self.config.amt_precision_post_satoshi != prec:
self.config.amt_precision_post_satoshi = prec self.config.amt_precision_post_satoshi = prec
self.config.set_key('amt_precision_post_satoshi', prec) self.config.set_key('amt_precision_post_satoshi', prec)
self.window.refresh_tabs() self.app.refresh_tabs_signal.emit()
msat_cb.stateChanged.connect(on_msat_checked) msat_cb.stateChanged.connect(on_msat_checked)
# units # units
@ -221,19 +227,16 @@ class SettingsDialog(WindowModalDialog):
unit_label = HelpLabel(_('Base unit') + ':', msg) unit_label = HelpLabel(_('Base unit') + ':', msg)
unit_combo = QComboBox() unit_combo = QComboBox()
unit_combo.addItems(units) unit_combo.addItems(units)
unit_combo.setCurrentIndex(units.index(self.window.base_unit())) unit_combo.setCurrentIndex(units.index(self.config.get_base_unit()))
def on_unit(x, nz): def on_unit(x, nz):
unit_result = units[unit_combo.currentIndex()] unit_result = units[unit_combo.currentIndex()]
if self.window.base_unit() == unit_result: if self.config.get_base_unit() == unit_result:
return return
edits = self.window.amount_e, self.window.receive_amount_e
amounts = [edit.get_amount() for edit in edits]
self.config.set_base_unit(unit_result) self.config.set_base_unit(unit_result)
nz.setMaximum(self.config.decimal_point) nz.setMaximum(self.config.decimal_point)
self.window.update_tabs() self.app.refresh_tabs_signal.emit()
for edit, amount in zip(edits, amounts): self.app.update_status_signal.emit()
edit.setAmount(amount) self.app.refresh_amount_edits_signal.emit()
self.window.update_status()
unit_combo.currentIndexChanged.connect(lambda x: on_unit(x, nz)) unit_combo.currentIndexChanged.connect(lambda x: on_unit(x, nz))
thousandsep_cb = QCheckBox(_("Add thousand separators to bitcoin amounts")) thousandsep_cb = QCheckBox(_("Add thousand separators to bitcoin amounts"))
@ -243,7 +246,7 @@ class SettingsDialog(WindowModalDialog):
if self.config.amt_add_thousands_sep != checked: if self.config.amt_add_thousands_sep != checked:
self.config.amt_add_thousands_sep = checked self.config.amt_add_thousands_sep = checked
self.config.set_key('amt_add_thousands_sep', checked) self.config.set_key('amt_add_thousands_sep', checked)
self.window.refresh_tabs() self.app.refresh_tabs_signal.emit()
thousandsep_cb.stateChanged.connect(on_set_thousandsep) thousandsep_cb.stateChanged.connect(on_set_thousandsep)
qr_combo = QComboBox() qr_combo = QComboBox()
@ -268,7 +271,6 @@ class SettingsDialog(WindowModalDialog):
colortheme_label = QLabel(_('Color theme') + ':') colortheme_label = QLabel(_('Color theme') + ':')
def on_colortheme(x): def on_colortheme(x):
self.config.set_key('qt_gui_color_theme', colortheme_combo.itemData(x), True) self.config.set_key('qt_gui_color_theme', colortheme_combo.itemData(x), True)
#self.window.gui_object.reload_app_stylesheet()
self.need_restart = True self.need_restart = True
colortheme_combo.currentIndexChanged.connect(on_colortheme) colortheme_combo.currentIndexChanged.connect(on_colortheme)
@ -294,14 +296,14 @@ class SettingsDialog(WindowModalDialog):
preview_cb.stateChanged.connect(on_preview) preview_cb.stateChanged.connect(on_preview)
usechange_cb = QCheckBox(_('Use change addresses')) usechange_cb = QCheckBox(_('Use change addresses'))
usechange_cb.setChecked(self.window.wallet.use_change) usechange_cb.setChecked(self.wallet.use_change)
if not self.config.is_modifiable('use_change'): usechange_cb.setEnabled(False) if not self.config.is_modifiable('use_change'): usechange_cb.setEnabled(False)
def on_usechange(x): def on_usechange(x):
usechange_result = x == Qt.Checked usechange_result = x == Qt.Checked
if self.window.wallet.use_change != usechange_result: if self.wallet.use_change != usechange_result:
self.window.wallet.use_change = usechange_result self.wallet.use_change = usechange_result
self.window.wallet.db.put('use_change', self.window.wallet.use_change) self.wallet.db.put('use_change', self.wallet.use_change)
multiple_cb.setEnabled(self.window.wallet.use_change) multiple_cb.setEnabled(self.wallet.use_change)
usechange_cb.stateChanged.connect(on_usechange) usechange_cb.stateChanged.connect(on_usechange)
usechange_cb.setToolTip(_('Using change addresses makes it more difficult for other people to track your transactions.')) usechange_cb.setToolTip(_('Using change addresses makes it more difficult for other people to track your transactions.'))
@ -407,7 +409,8 @@ class SettingsDialog(WindowModalDialog):
ex_combo = QComboBox() ex_combo = QComboBox()
def update_currencies(): def update_currencies():
if not self.window.fx: return if not self.fx:
return
currencies = sorted(self.fx.get_currencies(self.fx.get_history_config())) currencies = sorted(self.fx.get_currencies(self.fx.get_history_config()))
ccy_combo.clear() ccy_combo.clear()
ccy_combo.addItems([_('None')] + currencies) ccy_combo.addItems([_('None')] + currencies)
@ -453,7 +456,7 @@ class SettingsDialog(WindowModalDialog):
self.fx.set_currency(ccy) self.fx.set_currency(ccy)
update_history_cb() update_history_cb()
update_exchanges() update_exchanges()
self.window.update_fiat() self.app.update_fiat_signal.emit()
def on_exchange(idx): def on_exchange(idx):
exchange = str(ex_combo.currentText()) exchange = str(ex_combo.currentText())
@ -464,21 +467,20 @@ class SettingsDialog(WindowModalDialog):
if not self.fx: return if not self.fx: return
self.fx.set_history_config(checked) self.fx.set_history_config(checked)
update_exchanges() update_exchanges()
self.window.history_model.refresh('on_history')
if self.fx.is_enabled() and checked: if self.fx.is_enabled() and checked:
self.fx.trigger_update() self.fx.trigger_update()
update_history_capgains_cb() update_history_capgains_cb()
self.app.update_fiat_signal.emit()
def on_history_capgains(checked): def on_history_capgains(checked):
if not self.fx: return if not self.fx: return
self.fx.set_history_capital_gains_config(checked) self.fx.set_history_capital_gains_config(checked)
self.window.history_model.refresh('on_history_capgains') self.app.update_fiat_signal.emit()
def on_fiat_address(checked): def on_fiat_address(checked):
if not self.fx: return if not self.fx: return
self.fx.set_fiat_address_config(checked) self.fx.set_fiat_address_config(checked)
self.window.address_list.refresh_headers() self.app.update_fiat_signal.emit()
self.window.address_list.update()
update_currencies() update_currencies()
update_history_cb() update_history_cb()
@ -531,8 +533,8 @@ class SettingsDialog(WindowModalDialog):
tabs_info = [ tabs_info = [
(gui_widgets, _('Appearance')), (gui_widgets, _('Appearance')),
(invoices_widgets, _('Invoices')),
(tx_widgets, _('Transactions')), (tx_widgets, _('Transactions')),
(invoices_widgets, _('Invoices')),
(lightning_widgets, _('Lightning')), (lightning_widgets, _('Lightning')),
(fiat_widgets, _('Fiat')), (fiat_widgets, _('Fiat')),
(misc_widgets, _('Misc')), (misc_widgets, _('Misc')),
@ -558,12 +560,16 @@ class SettingsDialog(WindowModalDialog):
vbox.addLayout(Buttons(CloseButton(self))) vbox.addLayout(Buttons(CloseButton(self)))
self.setLayout(vbox) self.setLayout(vbox)
def on_network_callback(self, cb):
if cb == 'alias_received':
self.app.alias_received_signal.emit()
def set_alias_color(self): def set_alias_color(self):
if not self.config.get('alias'): if not self.config.get('alias'):
self.alias_e.setStyleSheet("") self.alias_e.setStyleSheet("")
return return
if self.window.alias_info: if self.wallet.contacts.alias_info:
alias_addr, alias_name, validated = self.window.alias_info alias_addr, alias_name, validated = self.wallet.contacts.alias_info
self.alias_e.setStyleSheet((ColorScheme.GREEN if validated else ColorScheme.RED).as_stylesheet(True)) self.alias_e.setStyleSheet((ColorScheme.GREEN if validated else ColorScheme.RED).as_stylesheet(True))
else: else:
self.alias_e.setStyleSheet(ColorScheme.RED.as_stylesheet(True)) self.alias_e.setStyleSheet(ColorScheme.RED.as_stylesheet(True))
@ -573,4 +579,4 @@ class SettingsDialog(WindowModalDialog):
alias = str(self.alias_e.text()) alias = str(self.alias_e.text())
self.config.set_key('alias', alias, True) self.config.set_key('alias', alias, True)
if alias: if alias:
self.window.fetch_alias() self.wallet.contacts.fetch_openalias(self.config)

Loading…
Cancel
Save