diff --git a/gui/qt/exception_window.py b/gui/qt/exception_window.py index a603af5e..992fa59a 100644 --- a/gui/qt/exception_window.py +++ b/gui/qt/exception_window.py @@ -57,6 +57,8 @@ class Exception_Window(QWidget): def __init__(self, main_window, exctype, value, tb): self.exc_args = (exctype, value, tb) + print(self.get_traceback_info()["exc_string"]) + print(self.get_traceback_info()["stack"]) self.main_window = main_window QWidget.__init__(self) self.setWindowTitle('Electrum - ' + _('An Error Occured')) diff --git a/gui/qt/lightning_invoice_list.py b/gui/qt/lightning_invoice_list.py new file mode 100644 index 00000000..5c7aa055 --- /dev/null +++ b/gui/qt/lightning_invoice_list.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- +import binascii +from PyQt5 import QtCore, QtWidgets +from collections import OrderedDict +import logging +from electrum.lightning import lightningCall + +mapping = {0: "r_hash", 1: "pay_req", 2: "settled"} +revMapp = {"r_hash": 0, "pay_req": 1, "settled": 2} +datatable = OrderedDict([]) +idx = 0 + +class MyTableRow(QtWidgets.QTreeWidgetItem): + def __init__(self, di): + strs = [str(di[mapping[key]]) for key in range(len(mapping))] + print(strs) + super(MyTableRow, self).__init__(strs) + assert isinstance(di, dict) + self.di = di + def __getitem__(self, idx): + return self.di[idx] + def __setitem__(self, idx, val): + self.di[idx] = val + try: + self.setData(revMapp[idx], QtCore.Qt.DisplayRole, '{0}'.format(val)) + except IndexError: + logging.warning("Lightning Invoice field %s unknown", idx) + def __str__(self): + return str(self.di) + +def addInvoiceRow(new): + made = MyTableRow(new) + datatable[new["r_hash"]] = made + datatable.move_to_end(new["r_hash"], last=False) + return made + +class SatoshiCountSpinBox(QtWidgets.QSpinBox): + def keyPressEvent(self, e): + super(SatoshiCountSpinBox, self).keyPressEvent(e) + if QtCore.Qt.Key_Return == e.key(): + clickHandler(self) + +def clickHandler(numInput, treeView, lightningRpc): + print(numInput.value()) + global idx + obj = { + "r_hash": binascii.hexlify((int.from_bytes(bytearray.fromhex("9500edb0994b7bc23349193486b25c82097045db641f35fa988c0e849acdec29"), "big")+idx).to_bytes(byteorder="big", length=32)).decode("ascii"), + "pay_req": "lntb81920n1pdf258s" + str(idx), + "settled": False + } + treeView.insertTopLevelItem(0, addInvoiceRow(obj)) + idx += 1 + lightningCall(lightningRpc, "getinfo")() + +class LightningInvoiceList(QtWidgets.QWidget): + def create_menu(self, position): + menu = QtWidgets.QMenu() + pay_req = self._tv.currentItem()["pay_req"] + cb = QtWidgets.QApplication.instance().clipboard() + def copy(): + print(pay_req) + cb.setText(pay_req) + menu.addAction("Copy payment request", copy) + menu.exec_(self._tv.viewport().mapToGlobal(position)) + """ + A simple test widget to contain and own the model and table. + """ + def __init__(self, parent, lightningWorker, lightningRpc): + QtWidgets.QWidget.__init__(self, parent) + + lightningWorker.subscribe(lambda *args: print(args)) + lightningRpc.subscribe(lambda *args: print(args)) + + self._tv=QtWidgets.QTreeWidget(self) + self._tv.setHeaderLabels([mapping[i] for i in range(len(mapping))]) + self._tv.setColumnCount(len(mapping)) + self._tv.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) + self._tv.customContextMenuRequested.connect(self.create_menu) + + numInput = SatoshiCountSpinBox(self) + + button = QtWidgets.QPushButton('Add invoice', self) + button.clicked.connect(lambda: clickHandler(numInput, self._tv, lightningRpc)) + + l=QtWidgets.QVBoxLayout(self) + h=QtWidgets.QGridLayout(self) + h.addWidget(numInput, 0, 0) + h.addWidget(button, 0, 1) + #h.addItem(QtWidgets.QSpacerItem(100, 200, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred), 0, 2) + #h.setSizePolicy( + h.setColumnStretch(0, 1) + h.setColumnStretch(1, 1) + h.setColumnStretch(2, 2) + l.addLayout(h) + l.addWidget(self._tv) + + self.resize(2500,1000) + +def tick(): + key = "9500edb0994b7bc23349193486b25c82097045db641f35fa988c0e849acdec29" + if not key in datatable: + return + row = datatable[key] + row["settled"] = not row["settled"] + print("data changed") + +if __name__=="__main__": + from sys import argv, exit + + a=QtWidgets.QApplication(argv) + + w=LightningInvoiceList() + w.show() + w.raise_() + + timer = QtCore.QTimer() + timer.timeout.connect(tick) + timer.start(1000) + exit(a.exec_()) diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py index 65369e1b..7e71145f 100644 --- a/gui/qt/main_window.py +++ b/gui/qt/main_window.py @@ -147,6 +147,9 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): tabs.addTab(self.send_tab, QIcon(":icons/tab_send.png"), _('Send')) tabs.addTab(self.receive_tab, QIcon(":icons/tab_receive.png"), _('Receive')) + self.lightning_invoices_tab = self.create_lightning_invoices_tab(wallet) + tabs.addTab(self.lightning_invoices_tab, _("Lightning Invoices")) + def add_optional_tab(tabs, tab, icon, description, name): tab.tab_icon = icon tab.tab_description = description @@ -750,6 +753,11 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): self.invoice_list.update() self.update_completions() + def create_lightning_invoices_tab(self, wallet): + from .lightning_invoice_list import LightningInvoiceList + self.lightning_invoice_list = LightningInvoiceList(self, wallet.lightningworker, wallet.lightning) + return self.lightning_invoice_list + def create_history_tab(self): from .history_list import HistoryList self.history_list = l = HistoryList(self) diff --git a/testserver.py b/testserver.py new file mode 100644 index 00000000..218d9dbe --- /dev/null +++ b/testserver.py @@ -0,0 +1,13 @@ +import asyncio + +async def handler(reader, writer): + magic = await reader.read(6) + await asyncio.sleep(5) + print("in five sec!") + await asyncio.sleep(5) + writer.write(b'{\n "r_preimage": "6UNoNhDZ/0awtaDTM7KuCtlYcNkNljscxMLleoJv9+o=",\n "r_hash": "t7IwR6zq8ZAfHaxvTnPmHdyt9j2tVd9g6TDg59C4juM=",\n "value": "8192",\n "settled": true,\n "creation_date": "1519994196",\n "settle_date": "1519994199",\n "payment_request": "lntb81920n1pdfj325pp5k7erq3avatceq8ca43h5uulxrhw2ma3a442a7c8fxrsw059c3m3sdqqcqzysdpwv4dn2xd74lfmea3taxj6pjfxrdl42t8w7ceptgv5ds0td0ypk47llryl6t4a48x54d7mnwremgcmljced4dhwty9g3pfywr307aqpwtkzf4",\n "expiry": "3600",\n "cltv_expiry": "144"\n}\n') + await writer.drain() + print(magic) + +asyncio.ensure_future(asyncio.start_server(handler, "127.0.0.1", 1080)) +asyncio.get_event_loop().run_forever()