|
|
@ -33,10 +33,10 @@ from decimal import Decimal |
|
|
|
import base64 |
|
|
|
from functools import partial |
|
|
|
|
|
|
|
import PyQt4 |
|
|
|
from PyQt4.QtGui import * |
|
|
|
from PyQt4.QtCore import * |
|
|
|
import PyQt4.QtCore as QtCore |
|
|
|
import PyQt5 |
|
|
|
from PyQt5.QtGui import * |
|
|
|
from PyQt5.QtCore import * |
|
|
|
import PyQt5.QtCore as QtCore |
|
|
|
|
|
|
|
from electrum.util import bh2u, bfh |
|
|
|
from . import icons_rc |
|
|
@ -81,7 +81,7 @@ class StatusBarButton(QPushButton): |
|
|
|
self.setIconSize(QSize(25,25)) |
|
|
|
|
|
|
|
def onPress(self, checked=False): |
|
|
|
'''Drops the unwanted PyQt4 "checked" argument''' |
|
|
|
'''Drops the unwanted PyQt5 "checked" argument''' |
|
|
|
self.func() |
|
|
|
|
|
|
|
def keyPressEvent(self, e): |
|
|
@ -94,6 +94,15 @@ from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED |
|
|
|
|
|
|
|
class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): |
|
|
|
|
|
|
|
payment_request_ok_signal = pyqtSignal() |
|
|
|
payment_request_error_signal = pyqtSignal() |
|
|
|
new_fx_quotes_signal = pyqtSignal() |
|
|
|
new_fx_history_signal = pyqtSignal() |
|
|
|
network_signal = pyqtSignal(str, object) |
|
|
|
alias_received_signal = pyqtSignal() |
|
|
|
computing_privkeys_signal = pyqtSignal() |
|
|
|
show_privkeys_signal = pyqtSignal() |
|
|
|
|
|
|
|
def __init__(self, gui_object, wallet): |
|
|
|
QMainWindow.__init__(self) |
|
|
|
|
|
|
@ -167,13 +176,13 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): |
|
|
|
for i in range(wrtabs.count()): |
|
|
|
QShortcut(QKeySequence("Alt+" + str(i + 1)), self, lambda i=i: wrtabs.setCurrentIndex(i)) |
|
|
|
|
|
|
|
self.connect(self, QtCore.SIGNAL('payment_request_ok'), self.payment_request_ok) |
|
|
|
self.connect(self, QtCore.SIGNAL('payment_request_error'), self.payment_request_error) |
|
|
|
self.payment_request_ok_signal.connect(self.payment_request_ok) |
|
|
|
self.payment_request_error_signal.connect(self.payment_request_error) |
|
|
|
self.history_list.setFocus(True) |
|
|
|
|
|
|
|
# network callbacks |
|
|
|
if self.network: |
|
|
|
self.connect(self, QtCore.SIGNAL('network'), self.on_network_qt) |
|
|
|
self.network_signal.connect(self.on_network_qt) |
|
|
|
interests = ['updated', 'new_transaction', 'status', |
|
|
|
'banner', 'verified', 'fee'] |
|
|
|
# To avoid leaking references to "self" that prevent the |
|
|
@ -185,8 +194,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): |
|
|
|
self.console.showMessage(self.network.banner) |
|
|
|
self.network.register_callback(self.on_quotes, ['on_quotes']) |
|
|
|
self.network.register_callback(self.on_history, ['on_history']) |
|
|
|
self.connect(self, SIGNAL('new_fx_quotes'), self.on_fx_quotes) |
|
|
|
self.connect(self, SIGNAL('new_fx_history'), self.on_fx_history) |
|
|
|
self.new_fx_quotes_signal.connect(self.on_fx_quotes) |
|
|
|
self.new_fx_history_signal.connect(self.on_fx_history) |
|
|
|
|
|
|
|
# update fee slider in case we missed the callback |
|
|
|
self.fee_slider.update() |
|
|
@ -195,7 +204,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): |
|
|
|
self.fetch_alias() |
|
|
|
|
|
|
|
def on_history(self, b): |
|
|
|
self.emit(SIGNAL('new_fx_history')) |
|
|
|
self.new_fx_history_signal.emit() |
|
|
|
|
|
|
|
def on_fx_history(self): |
|
|
|
self.history_list.refresh_headers() |
|
|
@ -203,7 +212,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): |
|
|
|
self.address_list.update() |
|
|
|
|
|
|
|
def on_quotes(self, b): |
|
|
|
self.emit(SIGNAL('new_fx_quotes')) |
|
|
|
self.new_fx_quotes_signal.emit() |
|
|
|
|
|
|
|
def on_fx_quotes(self): |
|
|
|
self.update_status() |
|
|
@ -275,17 +284,18 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): |
|
|
|
def on_network(self, event, *args): |
|
|
|
if event == 'updated': |
|
|
|
self.need_update.set() |
|
|
|
self.emit(QtCore.SIGNAL('updated'), event, *args) |
|
|
|
self.gui_object.network_updated_signal_obj.network_updated_signal \ |
|
|
|
.emit(event, args) |
|
|
|
|
|
|
|
elif event == 'new_transaction': |
|
|
|
self.tx_notifications.append(args[0]) |
|
|
|
elif event in ['status', 'banner', 'verified', 'fee']: |
|
|
|
# Handle in GUI thread |
|
|
|
self.emit(QtCore.SIGNAL('network'), event, *args) |
|
|
|
self.network_signal.emit(event, args) |
|
|
|
else: |
|
|
|
self.print_error("unexpected network message:", event, args) |
|
|
|
|
|
|
|
def on_network_qt(self, event, *args): |
|
|
|
def on_network_qt(self, event, args=None): |
|
|
|
# Handle a network message in the GUI thread |
|
|
|
if event == 'status': |
|
|
|
self.update_status() |
|
|
@ -307,7 +317,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): |
|
|
|
alias = str(alias) |
|
|
|
def f(): |
|
|
|
self.alias_info = self.contacts.resolve_openalias(alias) |
|
|
|
self.emit(SIGNAL('alias_received')) |
|
|
|
self.alias_received_signal.emit() |
|
|
|
t = threading.Thread(target=f) |
|
|
|
t.setDaemon(True) |
|
|
|
t.start() |
|
|
@ -380,7 +390,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): |
|
|
|
|
|
|
|
def open_wallet(self): |
|
|
|
wallet_folder = self.get_wallet_folder() |
|
|
|
filename = QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder) |
|
|
|
filename, __ = QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder) |
|
|
|
if not filename: |
|
|
|
return |
|
|
|
self.gui_object.new_window(filename) |
|
|
@ -389,7 +399,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): |
|
|
|
def backup_wallet(self): |
|
|
|
path = self.wallet.storage.path |
|
|
|
wallet_folder = os.path.dirname(path) |
|
|
|
filename = QFileDialog.getSaveFileName(self, _('Enter a filename for the copy of your wallet'), wallet_folder) |
|
|
|
filename, __ = QFileDialog.getSaveFileName(self, _('Enter a filename for the copy of your wallet'), wallet_folder) |
|
|
|
if not filename: |
|
|
|
return |
|
|
|
|
|
|
@ -574,7 +584,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): |
|
|
|
# custom wrappers for getOpenFileName and getSaveFileName, that remember the path selected by the user |
|
|
|
def getOpenFileName(self, title, filter = ""): |
|
|
|
directory = self.config.get('io_dir', os.path.expanduser('~')) |
|
|
|
fileName = QFileDialog.getOpenFileName(self, title, directory, filter) |
|
|
|
fileName, __ = QFileDialog.getOpenFileName(self, title, directory, filter) |
|
|
|
if fileName and directory != os.path.dirname(fileName): |
|
|
|
self.config.set_key('io_dir', os.path.dirname(fileName), True) |
|
|
|
return fileName |
|
|
@ -582,13 +592,13 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): |
|
|
|
def getSaveFileName(self, title, filename, filter = ""): |
|
|
|
directory = self.config.get('io_dir', os.path.expanduser('~')) |
|
|
|
path = os.path.join( directory, filename ) |
|
|
|
fileName = QFileDialog.getSaveFileName(self, title, path, filter) |
|
|
|
fileName, __ = QFileDialog.getSaveFileName(self, title, path, filter) |
|
|
|
if fileName and directory != os.path.dirname(fileName): |
|
|
|
self.config.set_key('io_dir', os.path.dirname(fileName), True) |
|
|
|
return fileName |
|
|
|
|
|
|
|
def connect_slots(self, sender): |
|
|
|
self.connect(sender, QtCore.SIGNAL('timersignal'), self.timer_actions) |
|
|
|
sender.timer_signal.connect(self.timer_actions) |
|
|
|
|
|
|
|
def timer_actions(self): |
|
|
|
# Note this runs in the GUI thread |
|
|
@ -1499,9 +1509,9 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): |
|
|
|
def on_pr(self, request): |
|
|
|
self.payment_request = request |
|
|
|
if self.payment_request.verify(self.contacts): |
|
|
|
self.emit(SIGNAL('payment_request_ok')) |
|
|
|
self.payment_request_ok_signal.emit() |
|
|
|
else: |
|
|
|
self.emit(SIGNAL('payment_request_error')) |
|
|
|
self.payment_request_error_signal.emit() |
|
|
|
|
|
|
|
def pay_to_URI(self, URI): |
|
|
|
if not URI: |
|
|
@ -1558,7 +1568,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): |
|
|
|
w.searchable_list = l |
|
|
|
vbox = QVBoxLayout() |
|
|
|
w.setLayout(vbox) |
|
|
|
vbox.setMargin(0) |
|
|
|
vbox.setContentsMargins(0, 0, 0, 0) |
|
|
|
vbox.setSpacing(0) |
|
|
|
vbox.addWidget(l) |
|
|
|
buttons = QWidget() |
|
|
@ -2121,16 +2131,16 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): |
|
|
|
if done: |
|
|
|
break |
|
|
|
private_keys[addr] = "\n".join(self.wallet.get_private_key(addr, password)) |
|
|
|
d.emit(SIGNAL('computing_privkeys')) |
|
|
|
d.emit(SIGNAL('show_privkeys')) |
|
|
|
self.computing_privkeys_signal.emit() |
|
|
|
self.show_privkeys_signal.emit() |
|
|
|
|
|
|
|
def show_privkeys(): |
|
|
|
s = "\n".join( map( lambda x: x[0] + "\t"+ x[1], private_keys.items())) |
|
|
|
e.setText(s) |
|
|
|
b.setEnabled(True) |
|
|
|
|
|
|
|
d.connect(d, QtCore.SIGNAL('computing_privkeys'), lambda: e.setText("Please wait... %d/%d"%(len(private_keys),len(addresses)))) |
|
|
|
d.connect(d, QtCore.SIGNAL('show_privkeys'), show_privkeys) |
|
|
|
self.computing_privkeys_signal.connect(lambda: e.setText("Please wait... %d/%d"%(len(private_keys),len(addresses)))) |
|
|
|
self.show_privkeys_signal.connect(show_privkeys) |
|
|
|
threading.Thread(target=privkeys_thread).start() |
|
|
|
|
|
|
|
if not d.exec_(): |
|
|
@ -2470,7 +2480,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): |
|
|
|
if alias: |
|
|
|
self.fetch_alias() |
|
|
|
set_alias_color() |
|
|
|
self.connect(self, SIGNAL('alias_received'), set_alias_color) |
|
|
|
self.alias_received_signal.connect(set_alias_color) |
|
|
|
alias_e.editingFinished.connect(on_alias_edit) |
|
|
|
id_widgets.append((alias_label, alias_e)) |
|
|
|
|
|
|
@ -2730,7 +2740,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): |
|
|
|
if self.fx: |
|
|
|
self.fx.timeout = 0 |
|
|
|
|
|
|
|
self.disconnect(self, SIGNAL('alias_received'), set_alias_color) |
|
|
|
self.alias_received_signal.disconnect(set_alias_color) |
|
|
|
|
|
|
|
run_hook('close_settings_dialog') |
|
|
|
if self.need_restart: |
|
|
|