tamountedit.py - electrum - Electrum Bitcoin wallet
HTML git clone https://git.parazyd.org/electrum
DIR Log
DIR Files
DIR Refs
DIR Submodules
---
tamountedit.py (4489B)
---
1 # -*- coding: utf-8 -*-
2
3 from decimal import Decimal
4 from typing import Union
5
6 from PyQt5.QtCore import pyqtSignal, Qt
7 from PyQt5.QtGui import QPalette, QPainter
8 from PyQt5.QtWidgets import (QLineEdit, QStyle, QStyleOptionFrame)
9
10 from .util import char_width_in_lineedit, ColorScheme
11
12 from electrum.util import (format_satoshis_plain, decimal_point_to_base_unit_name,
13 FEERATE_PRECISION, quantize_feerate)
14
15
16 class FreezableLineEdit(QLineEdit):
17 frozen = pyqtSignal()
18
19 def setFrozen(self, b):
20 self.setReadOnly(b)
21 self.setFrame(not b)
22 self.frozen.emit()
23
24 class AmountEdit(FreezableLineEdit):
25 shortcut = pyqtSignal()
26
27 def __init__(self, base_unit, is_int=False, parent=None):
28 QLineEdit.__init__(self, parent)
29 # This seems sufficient for hundred-BTC amounts with 8 decimals
30 self.setFixedWidth(16 * char_width_in_lineedit())
31 self.base_unit = base_unit
32 self.textChanged.connect(self.numbify)
33 self.is_int = is_int
34 self.is_shortcut = False
35 self.extra_precision = 0
36
37 def decimal_point(self):
38 return 8
39
40 def max_precision(self):
41 return self.decimal_point() + self.extra_precision
42
43 def numbify(self):
44 text = self.text().strip()
45 if text == '!':
46 self.shortcut.emit()
47 return
48 pos = self.cursorPosition()
49 chars = '0123456789'
50 if not self.is_int: chars +='.'
51 s = ''.join([i for i in text if i in chars])
52 if not self.is_int:
53 if '.' in s:
54 p = s.find('.')
55 s = s.replace('.','')
56 s = s[:p] + '.' + s[p:p+self.max_precision()]
57 self.setText(s)
58 # setText sets Modified to False. Instead we want to remember
59 # if updates were because of user modification.
60 self.setModified(self.hasFocus())
61 self.setCursorPosition(pos)
62
63 def paintEvent(self, event):
64 QLineEdit.paintEvent(self, event)
65 if self.base_unit:
66 panel = QStyleOptionFrame()
67 self.initStyleOption(panel)
68 textRect = self.style().subElementRect(QStyle.SE_LineEditContents, panel, self)
69 textRect.adjust(2, 0, -10, 0)
70 painter = QPainter(self)
71 painter.setPen(ColorScheme.GRAY.as_color())
72 painter.drawText(textRect, int(Qt.AlignRight | Qt.AlignVCenter), self.base_unit())
73
74 def get_amount(self) -> Union[None, Decimal, int]:
75 try:
76 return (int if self.is_int else Decimal)(str(self.text()))
77 except:
78 return None
79
80 def setAmount(self, x):
81 self.setText("%d"%x)
82
83
84 class BTCAmountEdit(AmountEdit):
85
86 def __init__(self, decimal_point, is_int=False, parent=None):
87 AmountEdit.__init__(self, self._base_unit, is_int, parent)
88 self.decimal_point = decimal_point
89
90 def _base_unit(self):
91 return decimal_point_to_base_unit_name(self.decimal_point())
92
93 def get_amount(self):
94 # returns amt in satoshis
95 try:
96 x = Decimal(str(self.text()))
97 except:
98 return None
99 # scale it to max allowed precision, make it an int
100 power = pow(10, self.max_precision())
101 max_prec_amount = int(power * x)
102 # if the max precision is simply what unit conversion allows, just return
103 if self.max_precision() == self.decimal_point():
104 return max_prec_amount
105 # otherwise, scale it back to the expected unit
106 amount = Decimal(max_prec_amount) / pow(10, self.max_precision()-self.decimal_point())
107 return Decimal(amount) if not self.is_int else int(amount)
108
109 def setAmount(self, amount_sat):
110 if amount_sat is None:
111 self.setText(" ") # Space forces repaint in case units changed
112 else:
113 self.setText(format_satoshis_plain(amount_sat, decimal_point=self.decimal_point()))
114 self.repaint() # macOS hack for #6269
115
116
117 class FeerateEdit(BTCAmountEdit):
118
119 def __init__(self, decimal_point, is_int=False, parent=None):
120 super().__init__(decimal_point, is_int, parent)
121 self.extra_precision = FEERATE_PRECISION
122
123 def _base_unit(self):
124 return 'sat/byte'
125
126 def get_amount(self):
127 sat_per_byte_amount = BTCAmountEdit.get_amount(self)
128 return quantize_feerate(sat_per_byte_amount)
129
130 def setAmount(self, amount):
131 amount = quantize_feerate(amount)
132 super().setAmount(amount)