electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

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