qt BTCAmountEdit: clamp field to <=21 million bitcoins
fixes https://github.com/spesmilo/electrum/issues/5223
This commit is contained in:
@@ -11,6 +11,10 @@ from .util import char_width_in_lineedit, ColorScheme
|
|||||||
|
|
||||||
from electrum.util import (format_satoshis_plain, decimal_point_to_base_unit_name,
|
from electrum.util import (format_satoshis_plain, decimal_point_to_base_unit_name,
|
||||||
FEERATE_PRECISION, quantize_feerate)
|
FEERATE_PRECISION, quantize_feerate)
|
||||||
|
from electrum.bitcoin import COIN, TOTAL_COIN_SUPPLY_LIMIT_IN_BTC
|
||||||
|
|
||||||
|
|
||||||
|
_NOT_GIVEN = object() # sentinel value
|
||||||
|
|
||||||
|
|
||||||
class FreezableLineEdit(QLineEdit):
|
class FreezableLineEdit(QLineEdit):
|
||||||
@@ -38,7 +42,7 @@ class SizedFreezableLineEdit(FreezableLineEdit):
|
|||||||
class AmountEdit(SizedFreezableLineEdit):
|
class AmountEdit(SizedFreezableLineEdit):
|
||||||
shortcut = pyqtSignal()
|
shortcut = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, base_unit, is_int=False, parent=None):
|
def __init__(self, base_unit, is_int=False, parent=None, *, max_amount=None):
|
||||||
# This seems sufficient for hundred-BTC amounts with 8 decimals
|
# This seems sufficient for hundred-BTC amounts with 8 decimals
|
||||||
width = 16 * char_width_in_lineedit()
|
width = 16 * char_width_in_lineedit()
|
||||||
super().__init__(width=width, parent=parent)
|
super().__init__(width=width, parent=parent)
|
||||||
@@ -47,6 +51,7 @@ class AmountEdit(SizedFreezableLineEdit):
|
|||||||
self.is_int = is_int
|
self.is_int = is_int
|
||||||
self.is_shortcut = False
|
self.is_shortcut = False
|
||||||
self.extra_precision = 0
|
self.extra_precision = 0
|
||||||
|
self.max_amount = max_amount
|
||||||
|
|
||||||
def decimal_point(self):
|
def decimal_point(self):
|
||||||
return 8
|
return 8
|
||||||
@@ -68,6 +73,9 @@ class AmountEdit(SizedFreezableLineEdit):
|
|||||||
p = s.find('.')
|
p = s.find('.')
|
||||||
s = s.replace('.','')
|
s = s.replace('.','')
|
||||||
s = s[:p] + '.' + s[p:p+self.max_precision()]
|
s = s[:p] + '.' + s[p:p+self.max_precision()]
|
||||||
|
if self.max_amount:
|
||||||
|
if (amt := self._get_amount_from_text(s)) and amt >= self.max_amount:
|
||||||
|
s = self._get_text_from_amount(self.max_amount)
|
||||||
self.setText(s)
|
self.setText(s)
|
||||||
# setText sets Modified to False. Instead we want to remember
|
# setText sets Modified to False. Instead we want to remember
|
||||||
# if updates were because of user modification.
|
# if updates were because of user modification.
|
||||||
@@ -92,7 +100,10 @@ class AmountEdit(SizedFreezableLineEdit):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def get_amount(self) -> Union[None, Decimal, int]:
|
def get_amount(self) -> Union[None, Decimal, int]:
|
||||||
return self._get_amount_from_text(str(self.text()))
|
amt = self._get_amount_from_text(str(self.text()))
|
||||||
|
if self.max_amount and amt and amt >= self.max_amount:
|
||||||
|
return self.max_amount
|
||||||
|
return amt
|
||||||
|
|
||||||
def _get_text_from_amount(self, amount) -> str:
|
def _get_text_from_amount(self, amount) -> str:
|
||||||
return "%d" % amount
|
return "%d" % amount
|
||||||
@@ -104,8 +115,10 @@ class AmountEdit(SizedFreezableLineEdit):
|
|||||||
|
|
||||||
class BTCAmountEdit(AmountEdit):
|
class BTCAmountEdit(AmountEdit):
|
||||||
|
|
||||||
def __init__(self, decimal_point, is_int=False, parent=None):
|
def __init__(self, decimal_point, is_int=False, parent=None, *, max_amount=_NOT_GIVEN):
|
||||||
AmountEdit.__init__(self, self._base_unit, is_int, parent)
|
if max_amount is _NOT_GIVEN:
|
||||||
|
max_amount = TOTAL_COIN_SUPPLY_LIMIT_IN_BTC * COIN
|
||||||
|
AmountEdit.__init__(self, self._base_unit, is_int, parent, max_amount=max_amount)
|
||||||
self.decimal_point = decimal_point
|
self.decimal_point = decimal_point
|
||||||
|
|
||||||
def _base_unit(self):
|
def _base_unit(self):
|
||||||
@@ -141,8 +154,8 @@ class BTCAmountEdit(AmountEdit):
|
|||||||
|
|
||||||
class FeerateEdit(BTCAmountEdit):
|
class FeerateEdit(BTCAmountEdit):
|
||||||
|
|
||||||
def __init__(self, decimal_point, is_int=False, parent=None):
|
def __init__(self, decimal_point, is_int=False, parent=None, *, max_amount=_NOT_GIVEN):
|
||||||
super().__init__(decimal_point, is_int, parent)
|
super().__init__(decimal_point, is_int, parent, max_amount=max_amount)
|
||||||
self.extra_precision = FEERATE_PRECISION
|
self.extra_precision = FEERATE_PRECISION
|
||||||
|
|
||||||
def _base_unit(self):
|
def _base_unit(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user