You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
323 lines
13 KiB
323 lines
13 KiB
from kivy.app import App
|
|
from kivy.factory import Factory
|
|
from kivy.properties import ObjectProperty
|
|
from kivy.lang import Builder
|
|
|
|
from electrum.util import base_units
|
|
from electrum.i18n import languages
|
|
from electrum_gui.kivy.i18n import _
|
|
from electrum.plugins import run_hook
|
|
from electrum import coinchooser
|
|
from electrum.util import fee_levels
|
|
|
|
from choice_dialog import ChoiceDialog
|
|
|
|
Builder.load_string('''
|
|
#:import partial functools.partial
|
|
#:import _ electrum_gui.kivy.i18n._
|
|
|
|
<SettingsItem@ButtonBehavior+BoxLayout>
|
|
orientation: 'vertical'
|
|
title: ''
|
|
description: ''
|
|
size_hint: 1, None
|
|
height: '60dp'
|
|
|
|
canvas.before:
|
|
Color:
|
|
rgba: (0.192, .498, 0.745, 1) if self.state == 'down' else (0.3, 0.3, 0.3, 0)
|
|
Rectangle:
|
|
size: self.size
|
|
pos: self.pos
|
|
on_release:
|
|
Clock.schedule_once(self.action)
|
|
|
|
Widget
|
|
TopLabel:
|
|
id: title
|
|
text: self.parent.title
|
|
bold: True
|
|
halign: 'left'
|
|
TopLabel:
|
|
text: self.parent.description
|
|
color: 0.8, 0.8, 0.8, 1
|
|
halign: 'left'
|
|
Widget
|
|
|
|
|
|
<SettingsDialog@Popup>
|
|
id: settings
|
|
title: _('Electrum Settings')
|
|
disable_pin: False
|
|
use_encryption: False
|
|
BoxLayout:
|
|
orientation: 'vertical'
|
|
ScrollView:
|
|
GridLayout:
|
|
id: scrollviewlayout
|
|
cols:1
|
|
size_hint: 1, None
|
|
height: self.minimum_height
|
|
padding: '10dp'
|
|
SettingsItem:
|
|
lang: settings.get_language_name()
|
|
title: 'Language' + ': ' + str(self.lang)
|
|
description: _('Language')
|
|
action: partial(root.language_dialog, self)
|
|
CardSeparator
|
|
SettingsItem:
|
|
status: '' if root.disable_pin else ('ON' if root.use_encryption else 'OFF')
|
|
disabled: root.disable_pin
|
|
title: _('PIN code') + ': ' + self.status
|
|
description: _("Change your PIN code.")
|
|
action: partial(root.change_password, self)
|
|
CardSeparator
|
|
SettingsItem:
|
|
bu: app.base_unit
|
|
title: _('Denomination') + ': ' + self.bu
|
|
description: _("Base unit for Bitcoin amounts.")
|
|
action: partial(root.unit_dialog, self)
|
|
CardSeparator
|
|
SettingsItem:
|
|
status: root.fee_status()
|
|
title: _('Fees') + ': ' + self.status
|
|
description: _("Fees paid to the Bitcoin miners.")
|
|
action: partial(root.fee_dialog, self)
|
|
CardSeparator
|
|
SettingsItem:
|
|
status: root.fx_status()
|
|
title: _('Fiat Currency') + ': ' + self.status
|
|
description: _("Display amounts in fiat currency.")
|
|
action: partial(root.fx_dialog, self)
|
|
CardSeparator
|
|
SettingsItem:
|
|
status: root.network_status()
|
|
title: _('Server') + ': ' + self.status
|
|
description: _("Select your history server.")
|
|
action: partial(root.network_dialog, self)
|
|
CardSeparator
|
|
SettingsItem:
|
|
status: root.proxy_status()
|
|
title: _('Proxy') + ': ' + self.status
|
|
description: _("Proxy configuration.")
|
|
action: partial(root.proxy_dialog, self)
|
|
CardSeparator
|
|
SettingsItem:
|
|
status: 'ON' if bool(app.plugins.get('labels')) else 'OFF'
|
|
title: _('Labels Sync') + ': ' + self.status
|
|
description: _("Save and synchronize your labels.")
|
|
action: partial(root.plugin_dialog, 'labels', self)
|
|
CardSeparator
|
|
SettingsItem:
|
|
status: root.rbf_status()
|
|
title: _('Replace-by-fee') + ': ' + self.status
|
|
description: _("Create replaceable transactions.")
|
|
action: partial(root.rbf_dialog, self)
|
|
CardSeparator
|
|
SettingsItem:
|
|
status: root.coinselect_status()
|
|
title: _('Coin selection') + ': ' + self.status
|
|
description: "Coin selection method"
|
|
action: partial(root.coinselect_dialog, self)
|
|
CardSeparator
|
|
SettingsItem:
|
|
status: "%d blocks"% app.num_blocks
|
|
title: _('Blockchain') + ': ' + self.status
|
|
description: _("Configure checkpoints")
|
|
action: partial(root.blockchain_dialog, self)
|
|
''')
|
|
|
|
|
|
|
|
class SettingsDialog(Factory.Popup):
|
|
|
|
def __init__(self, app):
|
|
self.app = app
|
|
self.plugins = self.app.plugins
|
|
self.config = self.app.electrum_config
|
|
Factory.Popup.__init__(self)
|
|
layout = self.ids.scrollviewlayout
|
|
layout.bind(minimum_height=layout.setter('height'))
|
|
# cached dialogs
|
|
self._fx_dialog = None
|
|
self._fee_dialog = None
|
|
self._rbf_dialog = None
|
|
self._network_dialog = None
|
|
self._proxy_dialog = None
|
|
self._language_dialog = None
|
|
self._unit_dialog = None
|
|
self._coinselect_dialog = None
|
|
self._blockchain_dialog = None
|
|
|
|
def update(self):
|
|
self.wallet = self.app.wallet
|
|
self.disable_pin = self.wallet.is_watching_only() if self.wallet else True
|
|
self.use_encryption = self.wallet.has_password() if self.wallet else False
|
|
|
|
def get_language_name(self):
|
|
return languages.get(self.config.get('language', 'en_UK'), '')
|
|
|
|
def change_password(self, item, dt):
|
|
self.app.change_password(self.update)
|
|
|
|
def language_dialog(self, item, dt):
|
|
if self._language_dialog is None:
|
|
l = self.config.get('language', 'en_UK')
|
|
def cb(key):
|
|
self.config.set_key("language", key, True)
|
|
item.lang = self.get_language_name()
|
|
self.app.language = key
|
|
self._language_dialog = ChoiceDialog(_('Language'), languages, l, cb)
|
|
self._language_dialog.open()
|
|
|
|
def unit_dialog(self, item, dt):
|
|
if self._unit_dialog is None:
|
|
def cb(text):
|
|
self.app._set_bu(text)
|
|
item.bu = self.app.base_unit
|
|
self._unit_dialog = ChoiceDialog(_('Denomination'), base_units.keys(), self.app.base_unit, cb)
|
|
self._unit_dialog.open()
|
|
|
|
def coinselect_status(self):
|
|
return coinchooser.get_name(self.app.electrum_config)
|
|
|
|
def coinselect_dialog(self, item, dt):
|
|
if self._coinselect_dialog is None:
|
|
choosers = sorted(coinchooser.COIN_CHOOSERS.keys())
|
|
chooser_name = coinchooser.get_name(self.config)
|
|
def cb(text):
|
|
self.config.set_key('coin_chooser', text)
|
|
item.status = text
|
|
self._coinselect_dialog = ChoiceDialog(_('Coin selection'), choosers, chooser_name, cb)
|
|
self._coinselect_dialog.open()
|
|
|
|
def blockchain_dialog(self, item, dt):
|
|
from checkpoint_dialog import CheckpointDialog
|
|
if self._blockchain_dialog is None:
|
|
def callback(height, value):
|
|
if value:
|
|
self.app.network.blockchain.set_checkpoint(height, value)
|
|
self._blockchain_dialog = CheckpointDialog(self.app.network, callback)
|
|
self._blockchain_dialog.open()
|
|
|
|
def proxy_status(self):
|
|
server, port, protocol, proxy, auto_connect = self.app.network.get_parameters()
|
|
return proxy.get('host') +':' + proxy.get('port') if proxy else _('None')
|
|
|
|
def proxy_dialog(self, item, dt):
|
|
if self._proxy_dialog is None:
|
|
server, port, protocol, proxy, auto_connect = self.app.network.get_parameters()
|
|
def callback(popup):
|
|
if popup.ids.mode.text != 'None':
|
|
proxy = {
|
|
'mode':popup.ids.mode.text,
|
|
'host':popup.ids.host.text,
|
|
'port':popup.ids.port.text,
|
|
'user':popup.ids.user.text,
|
|
'password':popup.ids.password.text
|
|
}
|
|
else:
|
|
proxy = None
|
|
self.app.network.set_parameters(server, port, protocol, proxy, auto_connect)
|
|
item.status = self.proxy_status()
|
|
popup = Builder.load_file('gui/kivy/uix/ui_screens/proxy.kv')
|
|
popup.ids.mode.text = proxy.get('mode') if proxy else 'None'
|
|
popup.ids.host.text = proxy.get('host') if proxy else ''
|
|
popup.ids.port.text = proxy.get('port') if proxy else ''
|
|
popup.ids.user.text = proxy.get('user') if proxy else ''
|
|
popup.ids.password.text = proxy.get('password') if proxy else ''
|
|
popup.on_dismiss = lambda: callback(popup)
|
|
self._proxy_dialog = popup
|
|
self._proxy_dialog.open()
|
|
|
|
def network_dialog(self, item, dt):
|
|
host, port, protocol, proxy, auto_connect = self.app.network.get_parameters()
|
|
servers = self.app.network.get_servers()
|
|
if self._network_dialog is None:
|
|
def cb1(popup):
|
|
host = str(popup.ids.host.text)
|
|
port = str(popup.ids.port.text)
|
|
auto_connect = popup.ids.auto_connect.active
|
|
self.app.network.set_parameters(host, port, protocol, proxy, auto_connect)
|
|
item.status = self.network_status()
|
|
def cb2(host):
|
|
from electrum.network import DEFAULT_PORTS
|
|
pp = servers.get(host, DEFAULT_PORTS)
|
|
port = pp.get(protocol, '')
|
|
popup.ids.host.text = host
|
|
popup.ids.port.text = port
|
|
def cb3():
|
|
ChoiceDialog(_('Choose a server'), sorted(servers), popup.ids.host.text, cb2).open()
|
|
popup = Builder.load_file('gui/kivy/uix/ui_screens/network.kv')
|
|
popup.ids.chooser.on_release = cb3
|
|
popup.on_dismiss = lambda: cb1(popup)
|
|
self._network_dialog = popup
|
|
|
|
self._network_dialog.ids.auto_connect.active = auto_connect
|
|
self._network_dialog.ids.host.text = host
|
|
self._network_dialog.ids.port.text = port
|
|
self._network_dialog.open()
|
|
|
|
def network_status(self):
|
|
server, port, protocol, proxy, auto_connect = self.app.network.get_parameters()
|
|
return 'auto-connect' if auto_connect else server
|
|
|
|
def plugin_dialog(self, name, label, dt):
|
|
from checkbox_dialog import CheckBoxDialog
|
|
def callback(status):
|
|
self.plugins.enable(name) if status else self.plugins.disable(name)
|
|
label.status = 'ON' if status else 'OFF'
|
|
|
|
status = bool(self.plugins.get(name))
|
|
dd = self.plugins.descriptions.get(name)
|
|
descr = dd.get('description')
|
|
fullname = dd.get('fullname')
|
|
d = CheckBoxDialog(fullname, descr, status, callback)
|
|
d.open()
|
|
|
|
def fee_status(self):
|
|
if self.config.get('dynamic_fees', True):
|
|
return fee_levels[self.config.get('fee_level', 2)]
|
|
else:
|
|
return self.app.format_amount_and_units(self.config.fee_per_kb()) + '/kB'
|
|
|
|
def fee_dialog(self, label, dt):
|
|
if self._fee_dialog is None:
|
|
from fee_dialog import FeeDialog
|
|
def cb():
|
|
label.status = self.fee_status()
|
|
self._fee_dialog = FeeDialog(self.app, self.config, cb)
|
|
self._fee_dialog.open()
|
|
|
|
def rbf_status(self):
|
|
return 'ON' if self.config.get('use_rbf') else 'OFF'
|
|
|
|
def rbf_dialog(self, label, dt):
|
|
if self._rbf_dialog is None:
|
|
from checkbox_dialog import CheckBoxDialog
|
|
def cb(x):
|
|
self.config.set_key('use_rbf', x, True)
|
|
label.status = self.rbf_status()
|
|
msg = [_('If you check this box, your transactions will be marked as non-final,'),
|
|
_('and you will have the possiblity, while they are unconfirmed, to replace them with transactions that pays higher fees.'),
|
|
_('Note that some merchants do not accept non-final transactions until they are confirmed.')]
|
|
fullname = _('Replace by fee')
|
|
self._rbf_dialog = CheckBoxDialog(fullname, ' '.join(msg), self.config.get('use_rbf', False), cb)
|
|
self._rbf_dialog.open()
|
|
|
|
def fx_status(self):
|
|
fx = self.app.fx
|
|
if fx.is_enabled():
|
|
source = fx.exchange.name()
|
|
ccy = fx.get_currency()
|
|
return '%s [%s]' %(ccy, source)
|
|
else:
|
|
return _('None')
|
|
|
|
def fx_dialog(self, label, dt):
|
|
if self._fx_dialog is None:
|
|
from fx_dialog import FxDialog
|
|
def cb():
|
|
label.status = self.fx_status()
|
|
self._fx_dialog = FxDialog(self.app, self.plugins, self.config, cb)
|
|
self._fx_dialog.open()
|
|
|