1
0

Add fee slider class with network callback.

This commit is contained in:
ThomasV
2017-01-09 09:22:17 +01:00
parent f50111f15a
commit a2e7fc32ef
6 changed files with 122 additions and 94 deletions

43
gui/qt/fee_slider.py Normal file
View File

@@ -0,0 +1,43 @@
from electrum.i18n import _
import PyQt4
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import PyQt4.QtCore as QtCore
class FeeSlider(QSlider):
def __init__(self, window, config, callback):
QSlider.__init__(self, Qt.Horizontal)
self.config = config
self.fee_step = self.config.max_fee_rate() / 10
self.window = window
self.callback = callback
self.setToolTip('')
self.update()
self.valueChanged.connect(self.moved)
def moved(self, pos):
from electrum.util import fee_levels
dyn = self.config.is_dynfee()
fee_rate = self.config.dynfee(pos) if dyn else pos * self.fee_step
rate_str = self.window.format_amount(fee_rate) + ' ' + self.window.base_unit() + '/kB'
if dyn:
tooltip = fee_levels[pos] + '\n' + rate_str
else:
tooltip = rate_str
if self.config.has_fee_estimates():
i = self.config.reverse_dynfee(fee_rate)
tooltip += '\n' + (_('low fee') if i < 0 else 'Within %d blocks'%i)
QToolTip.showText(QCursor.pos(), tooltip, self)
self.callback(dyn, pos, fee_rate)
def update(self):
if self.config.is_dynfee():
self.setRange(0, 4)
self.setValue(self.config.get('fee_level', 2))
else:
self.setRange(1, 10)
fee_rate = self.config.fee_per_kb()
pos = min(fee_rate / self.fee_step, 10)
self.setValue(pos)

View File

@@ -59,7 +59,7 @@ from network_dialog import NetworkDialog
from qrcodewidget import QRCodeWidget, QRDialog
from qrtextedit import ShowQRTextEdit
from transaction_dialog import show_transaction
from fee_slider import FeeSlider
from electrum import ELECTRUM_VERSION
@@ -161,7 +161,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
if self.network:
self.connect(self, QtCore.SIGNAL('network'), self.on_network_qt)
interests = ['updated', 'new_transaction', 'status',
'banner', 'verified']
'banner', 'verified', 'fee']
# To avoid leaking references to "self" that prevent the
# window from being GC-ed when closed, callbacks should be
# methods of this class only, and specifically not be
@@ -169,12 +169,13 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
self.network.register_callback(self.on_network, interests)
# set initial message
self.console.showMessage(self.network.banner)
self.network.register_callback(self.on_quotes, ['on_quotes'])
self.network.register_callback(self.on_history, ['on_history'])
self.connect(self, SIGNAL('new_fx_quotes'), self.on_fx_quotes)
self.connect(self, SIGNAL('new_fx_history'), self.on_fx_history)
# update fee slider in case we missed the callback
self.fee_slider.update()
self.load_wallet(wallet)
self.connect_slots(gui_object.timer)
self.fetch_alias()
@@ -259,7 +260,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
self.need_update.set()
elif event == 'new_transaction':
self.tx_notifications.append(args[0])
elif event in ['status', 'banner', 'verified']:
elif event in ['status', 'banner', 'verified', 'fee']:
# Handle in GUI thread
self.emit(QtCore.SIGNAL('network'), event, *args)
else:
@@ -273,6 +274,9 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
self.console.showMessage(args[0])
elif event == 'verified':
self.history_list.update_item(*args)
elif event == 'fee':
if self.config.is_dynfee():
self.fee_slider.update()
else:
self.print_error("unexpected network_qt signal:", event, args)
@@ -996,13 +1000,19 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
+ _('A suggested fee is automatically added to this field. You may override it. The suggested fee increases with the size of the transaction.')
self.fee_e_label = HelpLabel(_('Fee'), msg)
fee_cb = lambda x: self.spend_max() if self.is_max else self.update_fee()
self.fee_slider = self.create_fee_slider(self, fee_cb)
self.fee_slider.setValue(self.config.get('fee_level', 2))
def fee_cb(dyn, pos, fee_rate):
if dyn:
self.config.set_key('fee_level', pos, False)
else:
self.config.set_key('fee_per_kb', fee_rate, False)
self.spend_max() if self.is_max else self.update_fee()
self.fee_slider = FeeSlider(self, self.config, fee_cb)
self.fee_slider.setFixedWidth(140)
self.fee_e = BTCAmountEdit(self.get_decimal_point)
self.fee_e.setVisible(self.config.get('show_fee', False))
if not self.config.get('show_fee', False):
self.fee_e.setVisible(False)
self.fee_e.textEdited.connect(self.update_fee)
# This is so that when the user blanks the fee and moves on,
# we go back to auto-calculate mode and put a fee back.
@@ -1275,9 +1285,9 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
if extra_fee:
msg.append( _("Additional fees") + ": " + self.format_amount_and_units(extra_fee) )
confirm_rate = self.config.get('confirm_fee', 200000)
confirm_rate = 2 * self.config.max_fee_rate()
if tx.get_fee() > confirm_rate * tx.estimated_size() / 1000:
msg.append(_('Warning')+ ': ' + _("The fee for this transaction seems unusually high."))
msg.append(_('Warning') + ': ' + _("The fee for this transaction seems unusually high."))
if self.wallet.has_password():
msg.append("")
@@ -2370,28 +2380,14 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
nz.valueChanged.connect(on_nz)
gui_widgets.append((nz_label, nz))
dynfee_cb = QCheckBox(_('Use static fees'))
dynfee_cb.setChecked(not self.config.get('dynamic_fees', True))
dynfee_cb.setToolTip(_("Do not use fees recommended by the server."))
fee_e = BTCkBEdit(self.get_decimal_point)
def on_fee(is_done):
if self.config.get('dynamic_fees', True):
return
v = fee_e.get_amount() or 0
self.config.set_key('fee_per_kb', v, is_done)
self.update_fee()
def update_feeperkb():
fee_e.setAmount(self.config.get('fee_per_kb', bitcoin.RECOMMENDED_FEE))
b = self.config.get('dynamic_fees', True)
fee_e.setEnabled(not b)
dynfee_cb = QCheckBox(_('Use dynamic fees'))
dynfee_cb.setChecked(self.config.get('dynamic_fees', True))
dynfee_cb.setToolTip(_("Use fees recommended by the server."))
def on_dynfee(x):
self.config.set_key('dynamic_fees', x != Qt.Checked)
update_feeperkb()
fee_e.editingFinished.connect(lambda: on_fee(True))
fee_e.textEdited.connect(lambda: on_fee(False))
self.config.set_key('dynamic_fees', x == Qt.Checked)
self.fee_slider.update()
dynfee_cb.stateChanged.connect(on_dynfee)
update_feeperkb()
fee_widgets.append((dynfee_cb, fee_e))
fee_widgets.append((dynfee_cb, None))
feebox_cb = QCheckBox(_('Edit fees manually'))
feebox_cb.setChecked(self.config.get('show_fee', False))
@@ -2767,25 +2763,6 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
vbox.addLayout(Buttons(CloseButton(d)))
d.exec_()
def create_fee_slider(self, parent, callback):
from electrum.util import fee_levels
from electrum.bitcoin import FEE_STEP, RECOMMENDED_FEE
fee_slider = QSlider(Qt.Horizontal, parent)
def slider_moved():
pos = fee_slider.sliderPosition()
self.config.set_key('fee_level', pos, False)
is_dyn = self.config.get('dynamic_fees') and self.network and self.network.dynfee(pos)
fee_rate = self.wallet.fee_per_kb(self.config)
tooltip = fee_levels[pos] + '\n' if is_dyn else ''
tooltip += self.format_amount(fee_rate) + ' ' + self.base_unit() + '/kB'
QToolTip.showText(QCursor.pos(), tooltip, self.fee_slider)
callback(fee_rate)
fee_slider.setRange(0, 4)
fee_slider.setToolTip('')
fee_slider.setValue(self.config.get('fee_level', 2))
fee_slider.valueChanged.connect(slider_moved)
return fee_slider
def bump_fee_dialog(self, tx):
is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(tx)
@@ -2799,12 +2776,11 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
fee_e.setAmount(fee * 1.5)
vbox.addWidget(fee_e)
def on_rate(fee_rate):
def on_rate(dyn, pos, fee_rate):
fee = fee_rate * tx_size / 1000
fee_e.setAmount(fee)
fee_slider = self.create_fee_slider(d, on_rate)
fee_slider = FeeSlider(self, self.config, on_rate)
vbox.addWidget(fee_slider)
cb = QCheckBox(_('Final'))
vbox.addWidget(cb)
vbox.addLayout(Buttons(CancelButton(d), OkButton(d)))