forked from bitcoinafterlife/bal-electrum-plugin
init
This commit is contained in:
331
balqt/preview_dialog.py
Normal file
331
balqt/preview_dialog.py
Normal file
@@ -0,0 +1,331 @@
|
||||
|
||||
import enum
|
||||
import copy
|
||||
import json
|
||||
import urllib.request
|
||||
import urllib.parse
|
||||
from functools import partial
|
||||
|
||||
from . import qt_resources
|
||||
if qt_resources.QT_VERSION == 5:
|
||||
from PyQt5.QtGui import QStandardItemModel, QStandardItem, QPalette, QColor
|
||||
from PyQt5.QtCore import Qt,QPersistentModelIndex, QModelIndex
|
||||
from PyQt5.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QPushButton, QLabel,QMenu,QAbstractItemView,QWidget)
|
||||
else:
|
||||
from PyQt6.QtGui import QStandardItemModel, QStandardItem, QPalette, QColor
|
||||
from PyQt6.QtCore import Qt,QPersistentModelIndex, QModelIndex
|
||||
from PyQt6.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QPushButton, QLabel,QMenu,QAbstractItemView,QWidget)
|
||||
|
||||
from electrum.i18n import _
|
||||
from electrum.gui.qt.util import (Buttons,read_QIcon, import_meta_gui, export_meta_gui,MessageBoxMixin)
|
||||
from electrum.util import write_json_file,read_json_file,FileImportFailed
|
||||
from electrum.gui.qt.my_treeview import MyTreeView
|
||||
from electrum.transaction import tx_from_any
|
||||
from electrum.network import Network
|
||||
|
||||
|
||||
from ..bal import BalPlugin
|
||||
from .. import willexecutors as Willexecutors
|
||||
from .. import util as Util
|
||||
from .. import will as Will
|
||||
from .baldialog import BalDialog
|
||||
|
||||
class PreviewList(MyTreeView):
|
||||
class Columns(MyTreeView.BaseColumnsEnum):
|
||||
LOCKTIME = enum.auto()
|
||||
TXID = enum.auto()
|
||||
WILLEXECUTOR = enum.auto()
|
||||
STATUS = enum.auto()
|
||||
|
||||
headers = {
|
||||
Columns.LOCKTIME: _('Locktime'),
|
||||
Columns.TXID: _('Txid'),
|
||||
Columns.WILLEXECUTOR: _('Will-Executor'),
|
||||
Columns.STATUS: _('Status'),
|
||||
}
|
||||
|
||||
ROLE_HEIR_KEY = Qt.ItemDataRole.UserRole + 2000
|
||||
key_role = ROLE_HEIR_KEY
|
||||
|
||||
def __init__(self, parent: 'BalWindow',will):
|
||||
super().__init__(
|
||||
parent=parent.window,
|
||||
stretch_column=self.Columns.TXID,
|
||||
)
|
||||
self.decimal_point=parent.bal_plugin.config.get_decimal_point
|
||||
self.setModel(QStandardItemModel(self))
|
||||
self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
|
||||
|
||||
|
||||
if not will is None:
|
||||
self.will = will
|
||||
else:
|
||||
self.will = parent.willitems
|
||||
|
||||
self.bal_window = parent
|
||||
self.wallet=parent.window.wallet
|
||||
self.setModel(QStandardItemModel(self))
|
||||
self.setSortingEnabled(True)
|
||||
self.std_model = self.model()
|
||||
self.config = parent.bal_plugin.config
|
||||
self.bal_plugin=self.bal_window.bal_plugin
|
||||
|
||||
self.update()
|
||||
|
||||
def create_menu(self, position):
|
||||
menu = QMenu()
|
||||
idx = self.indexAt(position)
|
||||
column = idx.column() or self.Columns.TXID
|
||||
selected_keys = []
|
||||
for s_idx in self.selected_in_column(self.Columns.TXID):
|
||||
sel_key = self.model().itemFromIndex(s_idx).data(0)
|
||||
selected_keys.append(sel_key)
|
||||
if selected_keys and idx.isValid():
|
||||
column_title = self.model().horizontalHeaderItem(column).text()
|
||||
column_data = '\n'.join(self.model().itemFromIndex(s_idx).text()
|
||||
for s_idx in self.selected_in_column(column))
|
||||
|
||||
menu.addAction(_("details").format(column_title), lambda: self.show_transaction(selected_keys)).setEnabled(len(selected_keys)<2)
|
||||
menu.addAction(_("check ").format(column_title), lambda: self.check_transactions(selected_keys))
|
||||
|
||||
menu.addSeparator()
|
||||
menu.addAction(_("delete").format(column_title), lambda: self.delete(selected_keys))
|
||||
|
||||
menu.exec(self.viewport().mapToGlobal(position))
|
||||
|
||||
def delete(self,selected_keys):
|
||||
for key in selected_keys:
|
||||
del self.will[key]
|
||||
try:
|
||||
del self.bal_window.willitems[key]
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
del self.bal_window.will[key]
|
||||
except:
|
||||
pass
|
||||
self.update()
|
||||
|
||||
def check_transactions(self,selected_keys):
|
||||
wout = {}
|
||||
for k in selected_keys:
|
||||
wout[k] = self.will[k]
|
||||
if wout:
|
||||
self.bal_window.check_transactions(wout)
|
||||
self.update()
|
||||
|
||||
def show_transaction(self,selected_keys):
|
||||
for key in selected_keys:
|
||||
self.bal_window.show_transaction(self.will[key].tx)
|
||||
|
||||
self.update()
|
||||
|
||||
def select(self,selected_keys):
|
||||
self.selected += selected_keys
|
||||
self.update()
|
||||
|
||||
def deselect(self,selected_keys):
|
||||
for key in selected_keys:
|
||||
self.selected.remove(key)
|
||||
self.update()
|
||||
|
||||
def update_will(self,will):
|
||||
self.will.update(will)
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
if self.will is None:
|
||||
return
|
||||
|
||||
current_key = self.get_role_data_for_current_item(col=self.Columns.TXID, role=self.ROLE_HEIR_KEY)
|
||||
self.model().clear()
|
||||
self.update_headers(self.__class__.headers)
|
||||
|
||||
|
||||
|
||||
|
||||
set_current = None
|
||||
for txid,bal_tx in self.will.items():
|
||||
if self.bal_window.bal_plugin._hide_replaced and bal_tx.get_status('REPLACED'):
|
||||
continue
|
||||
if self.bal_window.bal_plugin._hide_invalidated and bal_tx.get_status('INVALIDATED'):
|
||||
continue
|
||||
|
||||
|
||||
tx=bal_tx.tx
|
||||
labels = [""] * len(self.Columns)
|
||||
labels[self.Columns.LOCKTIME] = Util.locktime_to_str(tx.locktime)
|
||||
labels[self.Columns.TXID] = txid
|
||||
we = 'None'
|
||||
if bal_tx.we:
|
||||
we = bal_tx.we['url']
|
||||
labels[self.Columns.WILLEXECUTOR]=we
|
||||
status = bal_tx.status
|
||||
if len(bal_tx.status) > 53:
|
||||
status = "...{}".format(status[-50:])
|
||||
labels[self.Columns.STATUS] = status
|
||||
|
||||
|
||||
|
||||
items=[]
|
||||
for e in labels:
|
||||
if type(e)== list:
|
||||
try:
|
||||
items.append(QStandardItem(*e))
|
||||
except Exception as e:
|
||||
pass
|
||||
else:
|
||||
items.append(QStandardItem(str(e)))
|
||||
|
||||
#pal = QPalette()
|
||||
#pal.setColor(QPalette.ColorRole.Window, QColor(bal_tx.get_color()))
|
||||
#items[-1].setAutoFillBackground(True)
|
||||
#items[-1o].setPalette(pal)
|
||||
items[-1].setBackground(QColor(bal_tx.get_color()))
|
||||
|
||||
|
||||
self.model().insertRow(self.model().rowCount(), items)
|
||||
if txid == current_key:
|
||||
idx = self.model().index(row_count, self.Columns.TXID)
|
||||
set_current = QPersistentModelIndex(idx)
|
||||
self.set_current_idx(set_current)
|
||||
|
||||
def create_toolbar(self, config):
|
||||
toolbar, menu = self.create_toolbar_with_menu('')
|
||||
menu.addAction(_("Prepare"), self.build_transactions)
|
||||
menu.addAction(_("Display"), self.bal_window.preview_modal_dialog)
|
||||
menu.addAction(_("Sign"), self.ask_password_and_sign_transactions)
|
||||
menu.addAction(_("Export"), self.export_will)
|
||||
#menu.addAction(_("Import"), self.import_will)
|
||||
menu.addAction(_("Broadcast"), self.broadcast)
|
||||
menu.addAction(_("Check"), self.check)
|
||||
menu.addAction(_("Invalidate"), self.invalidate_will)
|
||||
prepareButton = QPushButton(_("Prepare"))
|
||||
prepareButton.clicked.connect(self.build_transactions)
|
||||
signButton = QPushButton(_("Sign"))
|
||||
signButton.clicked.connect(self.ask_password_and_sign_transactions)
|
||||
pushButton = QPushButton(_("Broadcast"))
|
||||
pushButton.clicked.connect(self.broadcast)
|
||||
displayButton = QPushButton(_("Display"))
|
||||
displayButton.clicked.connect(self.bal_window.preview_modal_dialog)
|
||||
hlayout = QHBoxLayout()
|
||||
widget = QWidget()
|
||||
hlayout.addWidget(prepareButton)
|
||||
hlayout.addWidget(signButton)
|
||||
hlayout.addWidget(pushButton)
|
||||
hlayout.addWidget(displayButton)
|
||||
widget.setLayout(hlayout)
|
||||
toolbar.insertWidget(2,widget)
|
||||
|
||||
return toolbar
|
||||
|
||||
def hide_replaced(self):
|
||||
self.bal_window.bal_plugin.hide_replaced()
|
||||
self.update()
|
||||
|
||||
def hide_invalidated(self):
|
||||
f.bal_window.bal_plugin.hide_invalidated()
|
||||
self.update()
|
||||
|
||||
def build_transactions(self):
|
||||
will = self.bal_window.prepare_will()
|
||||
if will:
|
||||
self.update_will(will)
|
||||
|
||||
def export_json_file(self,path):
|
||||
write_json_file(path, self.will)
|
||||
|
||||
def export_will(self):
|
||||
self.bal_window.export_will()
|
||||
self.update()
|
||||
|
||||
def import_will(self):
|
||||
self.bal_window.import_will()
|
||||
|
||||
def ask_password_and_sign_transactions(self):
|
||||
self.bal_window.ask_password_and_sign_transactions(callback=self.update)
|
||||
|
||||
def broadcast(self):
|
||||
self.bal_window.broadcast_transactions()
|
||||
self.update()
|
||||
|
||||
def check(self):
|
||||
self.bal_window.check_transactions(self.bal_window.willitems)
|
||||
self.update()
|
||||
|
||||
def invalidate_will(self):
|
||||
self.bal_window.invalidate_will()
|
||||
self.update()
|
||||
|
||||
class PreviewDialog(BalDialog,MessageBoxMixin):
|
||||
def __init__(self, bal_window, will):
|
||||
self.parent = bal_window.window
|
||||
BalDialog.__init__(self,bal_window = bal_window)
|
||||
self.bal_plugin = bal_window.bal_plugin
|
||||
self.gui_object = self.bal_plugin.gui_object
|
||||
self.config = self.bal_plugin.config
|
||||
self.bal_window = bal_window
|
||||
self.wallet = bal_window.window.wallet
|
||||
self.format_amount = bal_window.window.format_amount
|
||||
self.base_unit = bal_window.window.base_unit
|
||||
self.format_fiat_and_units = bal_window.window.format_fiat_and_units
|
||||
self.fx = bal_window.window.fx
|
||||
self.format_fee_rate = bal_window.window.format_fee_rate
|
||||
self.show_address = bal_window.window.show_address
|
||||
if not will:
|
||||
self.will = bal_window.willitems
|
||||
else:
|
||||
self.will = will
|
||||
self.setWindowTitle(_('Transactions Preview'))
|
||||
self.setMinimumSize(1000, 200)
|
||||
self.size_label = QLabel()
|
||||
self.transactions_list = PreviewList(self.bal_window,self.will)
|
||||
vbox = QVBoxLayout(self)
|
||||
vbox.addWidget(self.size_label)
|
||||
vbox.addWidget(self.transactions_list)
|
||||
buttonbox = QHBoxLayout()
|
||||
|
||||
b = QPushButton(_('Sign'))
|
||||
b.clicked.connect(self.transactions_list.ask_password_and_sign_transactions)
|
||||
buttonbox.addWidget(b)
|
||||
|
||||
b = QPushButton(_('Export Will'))
|
||||
b.clicked.connect(self.transactions_list.export_will)
|
||||
buttonbox.addWidget(b)
|
||||
|
||||
b = QPushButton(_('Broadcast'))
|
||||
b.clicked.connect(self.transactions_list.broadcast)
|
||||
buttonbox.addWidget(b)
|
||||
|
||||
b = QPushButton(_('Invalidate will'))
|
||||
b.clicked.connect(self.transactions_list.invalidate_will)
|
||||
buttonbox.addWidget(b)
|
||||
|
||||
vbox.addLayout(buttonbox)
|
||||
|
||||
self.update()
|
||||
|
||||
|
||||
def update_will(self,will):
|
||||
self.will.update(will)
|
||||
self.transactions_list.update_will(will)
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
self.transactions_list.update()
|
||||
|
||||
def is_hidden(self):
|
||||
return self.isMinimized() or self.isHidden()
|
||||
|
||||
def show_or_hide(self):
|
||||
if self.is_hidden():
|
||||
self.bring_to_top()
|
||||
else:
|
||||
self.hide()
|
||||
|
||||
def bring_to_top(self):
|
||||
self.show()
|
||||
self.raise_()
|
||||
|
||||
def closeEvent(self, event):
|
||||
event.accept()
|
||||
Reference in New Issue
Block a user