Once a user inputs a fee, retain it.
It has long been a minor annoyance that this isn't the default behaviour. Semantics are as follows: - Fees are calculated automatically, as usual, and shown in black - If the user inputs a fee, it is retained, and shown in blue to indicate it is user-overridden - The user can switch back to automatic fee calculation mode in two ways: press Clear, or blank out the fee field - User fees are also cleared by do_clear(), for instance when the payment is sent I have checked all usage combinations I could think of, including the ! case, and all work in a sensible and natural fashion. This also fixes issue #995.
This commit is contained in:
parent
250bb03034
commit
aa6de86c27
|
@ -45,6 +45,9 @@ class AmountEdit(MyLineEdit):
|
||||||
s = s.replace('.','')
|
s = s.replace('.','')
|
||||||
s = s[:p] + '.' + s[p:p+self.decimal_point()]
|
s = s[:p] + '.' + s[p:p+self.decimal_point()]
|
||||||
self.setText(s)
|
self.setText(s)
|
||||||
|
# setText sets Modified to False. Instead we want to remember
|
||||||
|
# if updates were because of user modification.
|
||||||
|
self.setModified(self.hasFocus())
|
||||||
self.setCursorPosition(pos)
|
self.setCursorPosition(pos)
|
||||||
|
|
||||||
def paintEvent(self, event):
|
def paintEvent(self, event):
|
||||||
|
|
|
@ -914,31 +914,37 @@ class ElectrumWindow(QMainWindow):
|
||||||
addr = self.payto_e.payto_address if self.payto_e.payto_address else self.dummy_address
|
addr = self.payto_e.payto_address if self.payto_e.payto_address else self.dummy_address
|
||||||
output = ('address', addr, sendable)
|
output = ('address', addr, sendable)
|
||||||
dummy_tx = Transaction.from_io(inputs, [output])
|
dummy_tx = Transaction.from_io(inputs, [output])
|
||||||
fee = self.wallet.estimated_fee(dummy_tx)
|
if not self.fee_e.isModified():
|
||||||
self.amount_e.setAmount(max(0,sendable-fee))
|
self.fee_e.setAmount(self.wallet.estimated_fee(dummy_tx))
|
||||||
|
self.amount_e.setAmount(max(0, sendable - self.fee_e.get_amount()))
|
||||||
self.amount_e.textEdited.emit("")
|
self.amount_e.textEdited.emit("")
|
||||||
self.fee_e.setAmount(fee)
|
|
||||||
|
|
||||||
self.amount_e.shortcut.connect(on_shortcut)
|
self.amount_e.shortcut.connect(on_shortcut)
|
||||||
|
|
||||||
self.payto_e.textChanged.connect(lambda: self.update_fee(False))
|
self.payto_e.textChanged.connect(lambda: self.update_fee())
|
||||||
self.amount_e.textEdited.connect(lambda: self.update_fee(False))
|
self.amount_e.textEdited.connect(lambda: self.update_fee())
|
||||||
self.fee_e.textEdited.connect(lambda: self.update_fee(True))
|
self.fee_e.textEdited.connect(lambda: 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.
|
||||||
|
self.fee_e.editingFinished.connect(lambda: self.update_fee())
|
||||||
|
|
||||||
def entry_changed():
|
def entry_changed():
|
||||||
if not self.not_enough_funds:
|
text = ""
|
||||||
palette = QPalette()
|
if self.not_enough_funds:
|
||||||
palette.setColor(self.amount_e.foregroundRole(), QColor('black'))
|
amt_color, fee_color = 'red', 'red'
|
||||||
text = ""
|
|
||||||
else:
|
|
||||||
palette = QPalette()
|
|
||||||
palette.setColor(self.amount_e.foregroundRole(), QColor('red'))
|
|
||||||
text = _( "Not enough funds" )
|
text = _( "Not enough funds" )
|
||||||
c, u, x = self.wallet.get_frozen_balance()
|
c, u, x = self.wallet.get_frozen_balance()
|
||||||
if c+u+x:
|
if c+u+x:
|
||||||
text += ' (' + self.format_amount(c+u+x).strip() + ' ' + self.base_unit() + ' ' +_("are frozen") + ')'
|
text += ' (' + self.format_amount(c+u+x).strip() + ' ' + self.base_unit() + ' ' +_("are frozen") + ')'
|
||||||
|
elif self.fee_e.isModified():
|
||||||
|
amt_color, fee_color = 'black', 'blue'
|
||||||
|
else:
|
||||||
|
amt_color, fee_color = 'black', 'black'
|
||||||
self.statusBar().showMessage(text)
|
self.statusBar().showMessage(text)
|
||||||
|
palette = QPalette()
|
||||||
|
palette.setColor(self.amount_e.foregroundRole(), QColor(amt_color))
|
||||||
self.amount_e.setPalette(palette)
|
self.amount_e.setPalette(palette)
|
||||||
|
palette.setColor(self.amount_e.foregroundRole(), QColor(fee_color))
|
||||||
self.fee_e.setPalette(palette)
|
self.fee_e.setPalette(palette)
|
||||||
|
|
||||||
self.amount_e.textChanged.connect(entry_changed)
|
self.amount_e.textChanged.connect(entry_changed)
|
||||||
|
@ -970,14 +976,20 @@ class ElectrumWindow(QMainWindow):
|
||||||
run_hook('create_send_tab', grid)
|
run_hook('create_send_tab', grid)
|
||||||
return w
|
return w
|
||||||
|
|
||||||
def update_fee(self, is_fee):
|
def update_fee(self):
|
||||||
|
'''Recalculate the fee. If the fee was manually input, retain it, but
|
||||||
|
still build the TX to see if there are enough funds.
|
||||||
|
'''
|
||||||
|
freeze_fee = (self.fee_e.isModified()
|
||||||
|
and (self.fee_e.text() or self.fee_e.hasFocus()))
|
||||||
outputs = self.payto_e.get_outputs()
|
outputs = self.payto_e.get_outputs()
|
||||||
amount = self.amount_e.get_amount()
|
amount = self.amount_e.get_amount()
|
||||||
fee = self.fee_e.get_amount() if is_fee else None
|
|
||||||
if amount is None:
|
if amount is None:
|
||||||
self.fee_e.setAmount(None)
|
if not freeze_fee:
|
||||||
|
self.fee_e.setAmount(None)
|
||||||
self.not_enough_funds = False
|
self.not_enough_funds = False
|
||||||
else:
|
else:
|
||||||
|
fee = self.fee_e.get_amount()
|
||||||
if not outputs:
|
if not outputs:
|
||||||
addr = self.payto_e.payto_address if self.payto_e.payto_address else self.dummy_address
|
addr = self.payto_e.payto_address if self.payto_e.payto_address else self.dummy_address
|
||||||
outputs = [('address', addr, amount)]
|
outputs = [('address', addr, amount)]
|
||||||
|
@ -986,7 +998,7 @@ class ElectrumWindow(QMainWindow):
|
||||||
self.not_enough_funds = False
|
self.not_enough_funds = False
|
||||||
except NotEnoughFunds:
|
except NotEnoughFunds:
|
||||||
self.not_enough_funds = True
|
self.not_enough_funds = True
|
||||||
if not is_fee:
|
if not freeze_fee:
|
||||||
fee = None if self.not_enough_funds else self.wallet.get_tx_fee(tx)
|
fee = None if self.not_enough_funds else self.wallet.get_tx_fee(tx)
|
||||||
self.fee_e.setAmount(fee)
|
self.fee_e.setAmount(fee)
|
||||||
|
|
||||||
|
@ -1287,7 +1299,7 @@ class ElectrumWindow(QMainWindow):
|
||||||
def set_frozen_state(self, addrs, freeze):
|
def set_frozen_state(self, addrs, freeze):
|
||||||
self.wallet.set_frozen_state(addrs, freeze)
|
self.wallet.set_frozen_state(addrs, freeze)
|
||||||
self.update_address_tab()
|
self.update_address_tab()
|
||||||
self.update_fee(False)
|
self.update_fee()
|
||||||
|
|
||||||
def create_list_tab(self, l):
|
def create_list_tab(self, l):
|
||||||
w = QWidget()
|
w = QWidget()
|
||||||
|
@ -1432,7 +1444,7 @@ class ElectrumWindow(QMainWindow):
|
||||||
def send_from_addresses(self, addrs):
|
def send_from_addresses(self, addrs):
|
||||||
self.set_pay_from(addrs)
|
self.set_pay_from(addrs)
|
||||||
self.tabs.setCurrentIndex(1)
|
self.tabs.setCurrentIndex(1)
|
||||||
self.update_fee(False)
|
self.update_fee()
|
||||||
|
|
||||||
def paytomany(self):
|
def paytomany(self):
|
||||||
self.tabs.setCurrentIndex(1)
|
self.tabs.setCurrentIndex(1)
|
||||||
|
@ -2477,7 +2489,7 @@ class ElectrumWindow(QMainWindow):
|
||||||
def on_fee(is_done):
|
def on_fee(is_done):
|
||||||
self.wallet.set_fee(fee_e.get_amount() or 0, is_done)
|
self.wallet.set_fee(fee_e.get_amount() or 0, is_done)
|
||||||
if not is_done:
|
if not is_done:
|
||||||
self.update_fee(False)
|
self.update_fee()
|
||||||
fee_e.editingFinished.connect(lambda: on_fee(True))
|
fee_e.editingFinished.connect(lambda: on_fee(True))
|
||||||
fee_e.textEdited.connect(lambda: on_fee(False))
|
fee_e.textEdited.connect(lambda: on_fee(False))
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ class Exchanger(threading.Thread):
|
||||||
def get_json(self, site, get_string):
|
def get_json(self, site, get_string):
|
||||||
resp = requests.request('GET', 'https://' + site + get_string, headers={"User-Agent":"Electrum"})
|
resp = requests.request('GET', 'https://' + site + get_string, headers={"User-Agent":"Electrum"})
|
||||||
return resp.json()
|
return resp.json()
|
||||||
|
|
||||||
def exchange(self, btc_amount, quote_currency):
|
def exchange(self, btc_amount, quote_currency):
|
||||||
with self.lock:
|
with self.lock:
|
||||||
if self.quote_currencies is None:
|
if self.quote_currencies is None:
|
||||||
|
@ -522,7 +522,7 @@ class Plugin(BasePlugin):
|
||||||
if exchange_rate is not None:
|
if exchange_rate is not None:
|
||||||
btc_amount = fiat_amount/exchange_rate
|
btc_amount = fiat_amount/exchange_rate
|
||||||
btc_e.setAmount(int(btc_amount*Decimal(COIN)))
|
btc_e.setAmount(int(btc_amount*Decimal(COIN)))
|
||||||
if fee_e: self.win.update_fee(False)
|
if fee_e: self.win.update_fee()
|
||||||
fiat_e.textEdited.connect(fiat_changed)
|
fiat_e.textEdited.connect(fiat_changed)
|
||||||
def btc_changed():
|
def btc_changed():
|
||||||
if self.exchanger is None:
|
if self.exchanger is None:
|
||||||
|
|
Loading…
Reference in New Issue