fee_slider.py (3597B)
1 import threading 2 3 from PyQt5.QtGui import QCursor 4 from PyQt5.QtCore import Qt 5 from PyQt5.QtWidgets import QSlider, QToolTip, QComboBox 6 7 from electrum.i18n import _ 8 9 class FeeComboBox(QComboBox): 10 11 def __init__(self, fee_slider): 12 QComboBox.__init__(self) 13 self.config = fee_slider.config 14 self.fee_slider = fee_slider 15 self.addItems([_('Static'), _('ETA'), _('Mempool')]) 16 self.setCurrentIndex((2 if self.config.use_mempool_fees() else 1) if self.config.is_dynfee() else 0) 17 self.currentIndexChanged.connect(self.on_fee_type) 18 self.help_msg = '\n'.join([ 19 _('Static: the fee slider uses static values'), 20 _('ETA: fee rate is based on average confirmation time estimates'), 21 _('Mempool based: fee rate is targeting a depth in the memory pool') 22 ] 23 ) 24 25 def on_fee_type(self, x): 26 self.config.set_key('mempool_fees', x==2) 27 self.config.set_key('dynamic_fees', x>0) 28 self.fee_slider.update() 29 30 31 class FeeSlider(QSlider): 32 33 def __init__(self, window, config, callback): 34 QSlider.__init__(self, Qt.Horizontal) 35 self.config = config 36 self.window = window 37 self.callback = callback 38 self.dyn = False 39 self.lock = threading.RLock() 40 self.update() 41 self.valueChanged.connect(self.moved) 42 self._active = True 43 44 def moved(self, pos): 45 with self.lock: 46 if self.dyn: 47 fee_rate = self.config.depth_to_fee(pos) if self.config.use_mempool_fees() else self.config.eta_to_fee(pos) 48 else: 49 fee_rate = self.config.static_fee(pos) 50 tooltip = self.get_tooltip(pos, fee_rate) 51 QToolTip.showText(QCursor.pos(), tooltip, self) 52 self.setToolTip(tooltip) 53 self.callback(self.dyn, pos, fee_rate) 54 55 def get_tooltip(self, pos, fee_rate): 56 mempool = self.config.use_mempool_fees() 57 target, estimate = self.config.get_fee_text(pos, self.dyn, mempool, fee_rate) 58 if self.dyn: 59 return _('Target') + ': ' + target + '\n' + _('Current rate') + ': ' + estimate 60 else: 61 return _('Fixed rate') + ': ' + target + '\n' + _('Estimate') + ': ' + estimate 62 63 def update(self): 64 with self.lock: 65 self.dyn = self.config.is_dynfee() 66 mempool = self.config.use_mempool_fees() 67 maxp, pos, fee_rate = self.config.get_fee_slider(self.dyn, mempool) 68 self.setRange(0, maxp) 69 self.setValue(pos) 70 tooltip = self.get_tooltip(pos, fee_rate) 71 self.setToolTip(tooltip) 72 73 def activate(self): 74 self._active = True 75 self.setStyleSheet('') 76 77 def deactivate(self): 78 self._active = False 79 # TODO it would be nice to find a platform-independent solution 80 # that makes the slider look as if it was disabled 81 self.setStyleSheet( 82 """ 83 QSlider::groove:horizontal { 84 border: 1px solid #999999; 85 height: 8px; 86 background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #B1B1B1); 87 margin: 2px 0; 88 } 89 90 QSlider::handle:horizontal { 91 background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #8f8f8f); 92 border: 1px solid #5c5c5c; 93 width: 12px; 94 margin: -2px 0; 95 border-radius: 3px; 96 } 97 """ 98 ) 99 100 def is_active(self): 101 return self._active