26 Commits

Author SHA1 Message Date
37a3beb757 wizard test 2026-05-20 06:22:25 -04:00
33040273fb removed timer 2026-05-19 13:42:00 -04:00
c2236b099b ics wb 2026-05-19 13:40:11 -04:00
b02c19b530 ics wb 2026-05-19 13:29:14 -04:00
4203d078c1 ics wb 2026-05-19 13:27:16 -04:00
ff90c72866 icsdebug content 2026-05-19 13:19:36 -04:00
69de61d724 quick fix ics 2026-05-19 13:08:25 -04:00
f4ee4adfb3 quick fix ics 2026-05-19 13:00:06 -04:00
242d1b137f some fix to thread qdialog 2026-05-19 12:41:41 -04:00
5726ad2943 icons size 2026-05-10 14:55:17 -04:00
6cb25d296c locktime,checkalive 2026-05-10 11:27:17 -04:00
fa64ca6bbb locktime,checkalive 2026-05-10 11:26:43 -04:00
0dcaade1b9 locktime,checkalive 2026-05-10 11:26:03 -04:00
fbfe0a1966 bitcoon 2026-05-10 11:24:03 -04:00
b87e55c10f calendar 2026-05-10 09:58:05 -04:00
41248cff36 baltx_fees help button 2026-05-10 09:08:30 -04:00
5ab0a4a659 2026-05-10 09:06:24 -04:00
cf4557298f toplevelwindow 2026-05-10 08:02:15 -04:00
6f4ffd1b89 icons 2026-05-10 07:43:30 -04:00
2881b35a8a win w 2026-05-10 07:39:58 -04:00
7538d2d2c5 windows 2026-05-10 07:30:53 -04:00
8d30d8021f print status bar command in calendar windows 2026-05-10 07:18:10 -04:00
685b1c4241 status bar 2026-05-10 01:02:32 -04:00
cccd3cc984 no heirs message 2026-05-10 00:26:19 -04:00
397da520c9 calendar prodid 2026-05-09 23:16:23 -04:00
f83f1b707b icon button 2026-05-09 23:01:08 -04:00
5 changed files with 164 additions and 100 deletions

6
bal.py
View File

@@ -51,7 +51,7 @@ class BalPlugin(BasePlugin):
__version__ = "0.2.8" #AUTOMATICALLY GENERATED DO NOT EDIT __version__ = "0.2.8" #AUTOMATICALLY GENERATED DO NOT EDIT
default_app={ default_app={
"Linux":"xdg-open", "Linux":"xdg-open",
"Windows":"start", "Windows":"cmd /c start",
"Darwin":"open" "Darwin":"open"
} }
chainname = constants.net.NET_NAME if constants.net.NET_NAME != "mainnet" else "bitcoin" chainname = constants.net.NET_NAME if constants.net.NET_NAME != "mainnet" else "bitcoin"
@@ -103,8 +103,8 @@ class BalPlugin(BasePlugin):
self.ALLOW_REPUSH = BalConfig(config, "bal_allow_repush", True) self.ALLOW_REPUSH = BalConfig(config, "bal_allow_repush", True)
self.FIRST_EXECUTION = BalConfig(config, "bal_first_execution", True) self.FIRST_EXECUTION = BalConfig(config, "bal_first_execution", True)
self.WELIST_SERVER = BalConfig(config,"bal_welist_server","https://welist.bitcoin-after.life/") self.WELIST_SERVER = BalConfig(config,"bal_welist_server","https://welist.bitcoin-after.life/")
self.EVENT_DESCRIPTION = BalConfig(config,"bal_event_description", "Will execution for $wallet_name\n $heirs_complete\n") self.EVENT_DESCRIPTION = BalConfig(config,"bal_event_description", "BAL will execution of $wallet_name\r\n heirs list: \r\n$heirs_complete")
self.EVENT_SUMMARY = BalConfig(config,"bal_event_summary", "Will execution of $wallet_name\n") self.EVENT_SUMMARY = BalConfig(config,"bal_event_summary", "BAL -Will execution of $wallet_name")
self.WILLEXECUTORS = BalConfig( self.WILLEXECUTORS = BalConfig(
config, config,
"bal_willexecutors", "bal_willexecutors",

BIN
icons/reload.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
icons/wizard.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

228
qt.py
View File

@@ -49,7 +49,7 @@ from PyQt6.QtWidgets import (QAbstractItemView, QCheckBox, QComboBox,
QLineEdit, QTextEdit, QMenu, QMenuBar, QPushButton, QLineEdit, QTextEdit, QMenu, QMenuBar, QPushButton,
QScrollArea, QSizePolicy, QSpinBox, QScrollArea, QSizePolicy, QSpinBox,
QStackedWidget, QStyle, QStyleOptionFrame, QStackedWidget, QStyle, QStyleOptionFrame,
QVBoxLayout, QWidget) QVBoxLayout, QWidget,QDialog)
from .bal import BalPlugin,BalTimestamp from .bal import BalPlugin,BalTimestamp
from .heirs import HEIR_DUST_AMOUNT, HEIR_REAL_AMOUNT, Heirs from .heirs import HEIR_DUST_AMOUNT, HEIR_REAL_AMOUNT, Heirs
@@ -83,8 +83,7 @@ class Plugin(BalPlugin):
title=_("Success"), title=_("Success"),
) )
return return
Util.print_var(window) top_level_window=window.top_level_window()
top_level_window= window.top_level_window
w = BalWindow(self, top_level_window) w = BalWindow(self, top_level_window)
self.bal_windows[top_level_window.winId] = w self.bal_windows[top_level_window.winId] = w
for child in window.children(): for child in window.children():
@@ -108,11 +107,10 @@ class Plugin(BalPlugin):
@hook @hook
def create_status_bar(self, sb): def create_status_bar(self, sb):
_logger.info("HOOK create status bar") _logger.info("HOOK create status bar")
return
b = StatusBarButton( b = StatusBarButton(
read_QIcon_from_bytes(self.bal_plugin.read_file("icons/bal32x32.png")), read_QIcon_from_bytes(self.read_file("icons/bal32x32.png")),
"Bal " + _("Bitcoin After Life"), "Bal " + _("Bitcoin After Life"),
partial(self.setup_dialog, sb), partial(self.settings_dialog, sb),
sb.height(), sb.height(),
) )
sb.addPermanentWidget(b) sb.addPermanentWidget(b)
@@ -152,11 +150,11 @@ class Plugin(BalPlugin):
_logger.debug("daemon wallet loaded") _logger.debug("daemon wallet loaded")
def get_window(self, window): def get_window(self, window):
window=window.top_level_window()
w = self.bal_windows.get(window.winId, None) w = self.bal_windows.get(window.winId, None)
if w is None: if w is None:
win=window.top_level_window() w = BalWindow(self, window)
w = BalWindow(self, win) self.bal_windows[window.winId] = w
self.bal_windows[win.winId] = w
return w return w
def requires_settings(self): def requires_settings(self):
@@ -189,11 +187,11 @@ class Plugin(BalPlugin):
self.extension = bool(keystore.get_passphrase(password)) self.extension = bool(keystore.get_passphrase(password))
return keystore.get_seed(password) return keystore.get_seed(password)
def settings_dialog(self, window, wallet): def settings_dialog(self, window=None, wallet=None):
d = BalDialog(window, self, self.get_window_title("Settings")) d = BalDialog(window, self, self.get_window_title("Settings"))
d.setMinimumSize(100, 200) d.setMinimumSize(100, 200)
qicon = read_QPixmap_from_bytes(self.read_file("icons/bal32x32.png")) qicon = read_QPixmap_from_bytes(self.read_file("icons/bal16x16.png"))
lbl_logo = QLabel() lbl_logo = QLabel()
lbl_logo.setPixmap(qicon) lbl_logo.setPixmap(qicon)
@@ -743,7 +741,7 @@ class BalWindow:
self.init_heirs_to_locktime(self.bal_plugin.ENABLE_MULTIVERSE.get()) self.init_heirs_to_locktime(self.bal_plugin.ENABLE_MULTIVERSE.get())
except Exception as e: except Exception as e:
log_error(e, self) log_error(e )
_logger.error(f"init_class_variables: {e}") _logger.error(f"init_class_variables: {e}")
raise e raise e
@@ -861,7 +859,7 @@ class BalWindow:
# payment_identifier=payment_identifier, # payment_identifier=payment_identifier,
) )
d.setWindowIcon( d.setWindowIcon(
read_QIcon_from_bytes(self.bal_plugin.read_file("icons/bal32x32.png")) read_QIcon_from_bytes(self.bal_plugin.read_file("icons/bal16x16.png"))
) )
except SerializationError as e: except SerializationError as e:
_logger.error("unable to deserialize the transaction") _logger.error("unable to deserialize the transaction")
@@ -1054,6 +1052,8 @@ class BalWindow:
error = False error = False
for url in willexecutors: for url in willexecutors:
if self.waiting_dialog._stopping:
return
willexecutor = willexecutors[url] willexecutor = willexecutors[url]
self.waiting_dialog.update(getMsg(willexecutors)) self.waiting_dialog.update(getMsg(willexecutors))
if "txs" in willexecutor: if "txs" in willexecutor:
@@ -1072,6 +1072,8 @@ class BalWindow:
del willexecutor["txs"] del willexecutor["txs"]
except Willexecutors.AlreadyPresentException: except Willexecutors.AlreadyPresentException:
for wid in willexecutor["txsids"]: for wid in willexecutor["txsids"]:
if self.waiting_dialog._stopping:
return
self.waiting_dialog.update( self.waiting_dialog.update(
"checking {} - {} : {}".format( "checking {} - {} : {}".format(
self.willitems[wid].we["url"], wid, "Waiting" self.willitems[wid].we["url"], wid, "Waiting"
@@ -1126,6 +1128,9 @@ class BalWindow:
def check_transactions_task(self, will): def check_transactions_task(self, will):
start = time.time() start = time.time()
for wid, w in will.items(): for wid, w in will.items():
if self.waiting_dialog._stopping:
return
if w.we:
self.waiting_dialog.update( self.waiting_dialog.update(
"checking transaction: {}\n willexecutor: {}".format(wid, w.we["url"]) "checking transaction: {}\n willexecutor: {}".format(wid, w.we["url"])
) )
@@ -1137,6 +1142,7 @@ class BalWindow:
def check_transactions(self, will): def check_transactions(self, will):
def on_success(result): def on_success(result):
if hasattr(self,"waiting_dialog"):
del self.waiting_dialog del self.waiting_dialog
self.update_all() self.update_all()
pass pass
@@ -1163,12 +1169,8 @@ class BalWindow:
def download_list(self, willexecutors, fn_on_success, fn_on_failure=None): def download_list(self, willexecutors, fn_on_success, fn_on_failure=None):
print("self.bal_window.download_list")
def on_success(result): def on_success(result):
# self.willexecutors.update(result) self.willexecutors.update(result)
print("ddownload list success")
print(fn_on_success)
print(result)
fn_on_success(result) fn_on_success(result)
def on_failure(exec_info): def on_failure(exec_info):
@@ -1178,7 +1180,7 @@ class BalWindow:
fn_on_failure = log_error fn_on_failure = log_error
welist_server = self.bal_plugin.WELIST_SERVER.get() welist_server = self.bal_plugin.WELIST_SERVER.get()
task = partial(Willexecutors.download_list, willexecutors, welist_server) task = partial(Willexecutors.download_list, willexecutors, welist_server)
msg = _(f"Downloadinf willexecutors list from {welist_server}") msg = _(f"Downloading willexecutors list from {welist_server}")
self.waiting_dialog = BalWaitingDialog( self.waiting_dialog = BalWaitingDialog(
self, msg, task, on_success, on_failure, exe=False self, msg, task, on_success, on_failure, exe=False
) )
@@ -1287,9 +1289,13 @@ class BalTxFeesWidget(QWidget):
"baltx_fees" "baltx_fees"
] ]
self.txfee_widget.valueChanged.connect(self.on_heir_tx_fees) self.txfee_widget.valueChanged.connect(self.on_heir_tx_fees)
label = ClickableLabel("Tx Fees:") #label = ClickableLabel("")
label.doubleClicked.connect(self.doubleclick) #label.doubleClicked.connect(self.doubleclick)
layout.addWidget(label) #layout.addWidget(label)
button = HelpButton(_("mining fees expressed in sats/vbyte to be used in the Bitcoin transaction.\nHigher value ensure your transaction will be confirmed"))
button.setText("")
button.setStyleSheet("font-size: 16px;")
layout.addWidget(button)
layout.addWidget(self.txfee_widget) layout.addWidget(self.txfee_widget)
def doubleclick(self, event=None): def doubleclick(self, event=None):
@@ -1407,8 +1413,11 @@ class BalTimeEditWidget(QWidget, _LockTimeEditor):
default_index = 1 default_index = 1
except Exception: except Exception:
default_index = 0 default_index = 0
hbox.addWidget(QLabel(self.label_text)) #hbox.addWidget(QLabel(self.label_text))
hbox.addWidget(HelpButton(self.help_text)) help_button=HelpButton(self.help_text)
help_button.setText(self.label_text)
#help_button.setStyleSheet("font-size: 155555);
hbox.addWidget(help_button)
self.combo.currentIndexChanged.connect(self.on_current_index_changed) self.combo.currentIndexChanged.connect(self.on_current_index_changed)
for w in self.editors: for w in self.editors:
@@ -1639,7 +1648,8 @@ class ThresholdTimeWidget(BalTimeEditWidget):
"If you fail to invalidate during this time, your transactions will be delivered to your heirs.\n\n" "If you fail to invalidate during this time, your transactions will be delivered to your heirs.\n\n"
f"{BalTimeEditWidget.help_text}" f"{BalTimeEditWidget.help_text}"
) )
label_text = "Check Alive:" label_text = "🚨"
#label_text = "Check Alive"
base_field = "threshold" base_field = "threshold"
def __init__(self, bal_window, parent, init_value=None): def __init__(self, bal_window, parent, init_value=None):
@@ -1657,7 +1667,8 @@ class LockTimeWidget(BalTimeEditWidget):
"Any time is needed transaction will be anticipated by 1day\n" "Any time is needed transaction will be anticipated by 1day\n"
f"{BalTimeEditWidget.help_text}" f"{BalTimeEditWidget.help_text}"
) )
label_text = "Delivery Time:" label_text = "🚛"
#label_text = "Locktime"
base_field = "locktime" base_field = "locktime"
def __init__(self, bal_window, parent, init_value=None): def __init__(self, bal_window, parent, init_value=None):
@@ -1726,11 +1737,11 @@ class WillSettingsWidget(QWidget):
alarm_start = BalCalendar.format_time(threshold) alarm_start = BalCalendar.format_time(threshold)
days_difference = (locktime - threshold).days days_difference = (locktime - threshold).days
heirs_details = "\n".join(f"{heir} - {self.bal_window.heirs[heir][0]}, {self.bal_window.heirs[heir][1]}" for heir in self.bal_window.heirs) heirs_details = "\r\n".join(f" {heir} - {self.bal_window.heirs[heir][0]}, {self.bal_window.heirs[heir][1]}" for heir in self.bal_window.heirs)
event_description = BalCalendar.ical_escape( event_description = BalCalendar.ical_escape(
f"{self.bal_window.bal_plugin.EVENT_DESCRIPTION.get()}".replace("$wallet_name",str(self.bal_window.wallet)).replace("$heirs_complete",heirs_details) f"{self.bal_window.bal_plugin.EVENT_DESCRIPTION.get()}".replace("$wallet_name",str(self.bal_window.wallet)).replace("$heirs_complete",heirs_details)
) )
event_description =f"{event_description}{heirs_details}" #event_description =f"{event_description}{heirs_details}"
uid = f"bal-{str(self.bal_window.wallet)}" uid = f"bal-{str(self.bal_window.wallet)}"
summary = BalCalendar.ical_escape( summary = BalCalendar.ical_escape(
f"{self.bal_window.bal_plugin.EVENT_SUMMARY.get()}".replace("$wallet_name",str(self.bal_window.wallet)) f"{self.bal_window.bal_plugin.EVENT_SUMMARY.get()}".replace("$wallet_name",str(self.bal_window.wallet))
@@ -1738,7 +1749,7 @@ class WillSettingsWidget(QWidget):
lines = [ lines = [
"BEGIN:VCALENDAR", "BEGIN:VCALENDAR",
"VERSION:2.0", "VERSION:2.0",
f"PRODID:-//Bitcoin After Life//Electrum Plugin/{BalPlugin.version}", f"PRODID:-//Bitcoin After Life//Electrum Plugin/{BalPlugin.__version__}",
"BEGIN:VEVENT", "BEGIN:VEVENT",
f"UID:{uid}", f"UID:{uid}",
f"DTSTAMP:{now}", f"DTSTAMP:{now}",
@@ -1753,6 +1764,7 @@ class WillSettingsWidget(QWidget):
"END:VCALENDAR", "END:VCALENDAR",
]) ])
lines = [s.rstrip("\r\n") for s in lines]
ics_content = "\r\n".join(lines) + "\r\n" ics_content = "\r\n".join(lines) + "\r\n"
self.temp_path = BalCalendar.write_temp_ics(ics_content) self.temp_path = BalCalendar.write_temp_ics(ics_content)
opened = BalCalendar.open_with_default_app( opened = BalCalendar.open_with_default_app(
@@ -1868,24 +1880,35 @@ class PercAmountEdit(BTCAmountEdit):
) )
class BalDialog(WindowModalDialog): class BalDialog(QDialog,MessageBoxMixin):
def __init__(self, parent, bal_plugin, title=None, icon="icons/bal32x32.png"): _stopping = False
def __init__(self, parent, bal_plugin, title=None, icon="icons/bal16x16.png"):
import signal
from PyQt6.QtCore import QMetaObject, Qt
from PyQt6.QtWidgets import QApplication
def handler(signum, frame):
QMetaObject.invokeMethod(self, "close", Qt.ConnectionType.QueuedConnection)
#signal.signal(signal.SIGINT, handler)
self.parent = parent self.parent = parent
self.thread = None self.thread = None
WindowModalDialog.__init__(self, parent, title) super().__init__(parent)
if title:
self.setWindowTitle(title)
# WindowModalDialog.__init__(self,parent) # WindowModalDialog.__init__(self,parent)
self.setWindowIcon(read_QIcon_from_bytes(bal_plugin.read_file(icon))) self.setWindowIcon(read_QIcon_from_bytes(bal_plugin.read_file(icon)))
def closeEvent(self, event): def closeEvent(self, event):
self._stopping = True self._stopping = True
if self.thread: #if self.thread:
self.thread.stop() # self.thread.stop()
super().closeEvent(event)
def hideEvent(self, event): def hideEvent(self, event):
self._stopping = True self._stopping = True
if self.thread: #if self.thread:
self.thread.stop() # self.thread.stop()
super().hideEvent(event)
class BalWizardDialog(BalDialog): class BalWizardDialog(BalDialog):
def __init__(self, bal_window: "BalWindow"): def __init__(self, bal_window: "BalWindow"):
@@ -2151,6 +2174,7 @@ class BalWizardWEDownloadWidget(BalWizardWidget):
# TODO DO NOTHING # TODO DO NOTHING
pass pass
self.bal_window.will_list_widget.update()
if self.validate(): if self.validate():
return self.on_next() return self.on_next()
@@ -2241,13 +2265,11 @@ class BalWaitingDialog(BalDialog):
pass pass
def finished(self): def finished(self):
_logger.info("finished") pass
def wait(self):
self.thread.wait()
def on_accepted(self): def on_accepted(self):
self.thread.stop() pass
def update_message(self, msg): def update_message(self, msg):
self.message_label.setText(msg) self.message_label.setText(msg)
@@ -2258,9 +2280,6 @@ class BalWaitingDialog(BalDialog):
def getText(self): def getText(self):
return self.message_label.text() return self.message_label.text()
def closeEvent(self, event):
self._stopping = True
self.thread.stop()
class BalBlockingWaitingDialog(BalDialog): class BalBlockingWaitingDialog(BalDialog):
@@ -2335,7 +2354,7 @@ class BalBuildWillDialog(BalDialog):
self.labelsbox = QVBoxLayout(self.qwidget) self.labelsbox = QVBoxLayout(self.qwidget)
self.setMinimumWidth(600) self.setMinimumWidth(600)
self.setMinimumHeight(100) self.setMinimumHeight(100)
self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred) self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
self.labels = [] self.labels = []
self.check_row = None self.check_row = None
self.inval_row = None self.inval_row = None
@@ -2362,6 +2381,8 @@ class BalBuildWillDialog(BalDialog):
self.exec() self.exec()
def task_phase1(self): def task_phase1(self):
if self._stopping:
return
txs = None txs = None
_logger.debug("close plugin phase 1 started") _logger.debug("close plugin phase 1 started")
varrow = self.msg_set_status("checking variables") varrow = self.msg_set_status("checking variables")
@@ -2376,15 +2397,14 @@ class BalBuildWillDialog(BalDialog):
_logger.debug( _logger.debug(
"during phase1 CAE: {}, Continue to invalidate".format(cae) "during phase1 CAE: {}, Continue to invalidate".format(cae)
) )
self.msg_set_checking( self.msg_set_status("checking variables",varrow, "Check Alive Threshold Passed: you have to Invalidate your old Will",self.COLOR_ERROR)
self.msg_warning(
"Check Alive Threshold Passed: you have to Invalidate your old Will"
)
)
else: else:
raise cae raise cae
return None, tx return None, tx
except NoHeirsException:
self.msg_set_status("checking variables", varrow,"No Heirs",self.COLOR_ERROR)
#self.msg_set_checking("No Heirs")
return False, None
except Exception as e: except Exception as e:
raise e raise e
try: try:
@@ -2422,7 +2442,6 @@ class BalBuildWillDialog(BalDialog):
except NoHeirsException as e: except NoHeirsException as e:
_logger.debug("no heirs") _logger.debug("no heirs")
self.msg_set_checking("No Heirs") self.msg_set_checking("No Heirs")
raise e
except NotCompleteWillException as e: except NotCompleteWillException as e:
_logger.debug(f"not complete {e} true") _logger.debug(f"not complete {e} true")
message = False message = False
@@ -2448,11 +2467,9 @@ class BalBuildWillDialog(BalDialog):
try: try:
txs = self.bal_window.build_will() txs = self.bal_window.build_will()
if not txs: if not txs:
self.msg_set_status( self.msg_set_building(
_("Balance is too low. No transaction was built"), _("Balance is too low, or CheckAlive is in the past.Skipped"),
None, color = self.COLOR_ERROR,
_("Skipped"),
self.COLOR_ERROR,
) )
return False, None return False, None
@@ -2509,6 +2526,8 @@ class BalBuildWillDialog(BalDialog):
self.msg_del_row(wait_row) self.msg_del_row(wait_row)
def loop_broadcast_invalidating(self, tx): def loop_broadcast_invalidating(self, tx):
if self._stopping:
return
self.msg_set_invalidating("Broadcasting") self.msg_set_invalidating("Broadcasting")
try: try:
tx.add_info_from_wallet(self.bal_window.wallet) tx.add_info_from_wallet(self.bal_window.wallet)
@@ -2528,6 +2547,8 @@ class BalBuildWillDialog(BalDialog):
self.msg_set_invalidating(self.msg_error(e)) self.msg_set_invalidating(self.msg_error(e))
def loop_push(self): def loop_push(self):
if self._stopping:
return
self.msg_set_pushing(_("Broadcasting")) self.msg_set_pushing(_("Broadcasting"))
retry = False retry = False
try: try:
@@ -2536,6 +2557,8 @@ class BalBuildWillDialog(BalDialog):
self.bal_window.willitems self.bal_window.willitems
) )
for url, willexecutor in willexecutors.items(): for url, willexecutor in willexecutors.items():
if self._stopping:
return
try: try:
if Willexecutors.is_selected( if Willexecutors.is_selected(
self.bal_window.willexecutors.get(url) self.bal_window.willexecutors.get(url)
@@ -2556,6 +2579,8 @@ class BalBuildWillDialog(BalDialog):
) )
except Willexecutors.AlreadyPresentException: except Willexecutors.AlreadyPresentException:
for wid in willexecutor["txsids"]: for wid in willexecutor["txsids"]:
if self._stopping:
return
row = self.msg_edit_row( row = self.msg_edit_row(
"checking {} - {} : {}".format( "checking {} - {} : {}".format(
self.bal_window.willitems[wid].we["url"], wid, "Waiting" self.bal_window.willitems[wid].we["url"], wid, "Waiting"
@@ -2590,6 +2615,8 @@ class BalBuildWillDialog(BalDialog):
# self.loop_push() # self.loop_push()
def invalidate_task(self, password, bal_window, tx): def invalidate_task(self, password, bal_window, tx):
if self._stopping:
return
_logger.debug(f"invalidate tx: {tx}") _logger.debug(f"invalidate tx: {tx}")
# fee_per_byte = bal_window.will_settings.get("baltx_fees", 1) # fee_per_byte = bal_window.will_settings.get("baltx_fees", 1)
tx = self.bal_window.wallet.sign_transaction(tx, password) tx = self.bal_window.wallet.sign_transaction(tx, password)
@@ -2616,6 +2643,8 @@ class BalBuildWillDialog(BalDialog):
) )
def on_success_phase1(self, result): def on_success_phase1(self, result):
if self._stopping:
return
self.have_to_sign, tx = list(result) self.have_to_sign, tx = list(result)
# if not tx: # if not tx:
# self.msg_edit_row(self.msg_error("Error, no tx was built")) # self.msg_edit_row(self.msg_error("Error, no tx was built"))
@@ -2671,6 +2700,8 @@ class BalBuildWillDialog(BalDialog):
self.thread.stop() self.thread.stop()
def task_phase2(self, password): def task_phase2(self, password):
if self._stopping:
return
if self.have_to_sign: if self.have_to_sign:
try: try:
if txs := self.bal_window.sign_transactions(password): if txs := self.bal_window.sign_transactions(password):
@@ -2709,7 +2740,11 @@ class BalBuildWillDialog(BalDialog):
a, b, c = error a, b, c = error
self.msg_edit_row(self.msg_error(f"Error: {b}")) self.msg_edit_row(self.msg_error(f"Error: {b}"))
_logger.error(f"error phase1: {b}") _logger.error(f"error phase1: {b}")
button=QPushButton(_("Close"))
button.clicked.connect(self.close)
self.vbox.addWidget(button)
self.resize(self.vbox.sizeHint()+button.sizeHint()*2)
self.repaint()
def on_error_phase2(self, error): def on_error_phase2(self, error):
self.bal_window.upade_all() self.bal_window.upade_all()
a, b, c = error a, b, c = error
@@ -2726,10 +2761,10 @@ class BalBuildWillDialog(BalDialog):
_("Invalidating old will"), self.inval_row, status _("Invalidating old will"), self.inval_row, status
) )
def msg_set_building(self, status=None, row=None): def msg_set_building(self, status=None, row=None,color=None):
row = self.build_row if row is None else row row = self.build_row if row is None else row
self.build_row = self.msg_set_status( self.build_row = self.msg_set_status(
"Building your will", self.build_row, status "Building your will", self.build_row, status, color
) )
def msg_set_signing(self, status=None, row=None): def msg_set_signing(self, status=None, row=None):
@@ -2755,8 +2790,11 @@ class BalBuildWillDialog(BalDialog):
def msg_warning(self, e): def msg_warning(self, e):
return "<font color='{}'>{}</font".format(self.COLOR_WARNING, e) return "<font color='{}'>{}</font".format(self.COLOR_WARNING, e)
def msg_set_status(self, msg, row=None, status=None, color="#000000"): def msg_set_status(self, msg, row=None, status=None, color=None):
status = "Wait" if status is None else status status = "Wait" if status is None else status
if color is None:
line = f"{_(msg)}:\t{status}"
else:
line = "<font color={}>{}:\t{}</font>".format(color, _(msg), status) line = "<font color={}>{}:\t{}</font>".format(color, _(msg), status)
return self.msg_edit_row(line, row) return self.msg_edit_row(line, row)
@@ -3241,12 +3279,22 @@ class PreviewList(MyTreeView, MessageBoxMixin):
menu.addAction(_("Check"), self.check) menu.addAction(_("Check"), self.check)
menu.addAction(_("Invalidate"), self.invalidate_will) menu.addAction(_("Invalidate"), self.invalidate_will)
wizard = QPushButton(_("Setup Wizard")) wizard = QPushButton()
wizard.setIcon(
read_QIcon_from_bytes(
self.bal_window.bal_plugin.read_file("icons/wizard.png")
)
)
wizard.clicked.connect(self.bal_window.init_wizard) wizard.clicked.connect(self.bal_window.init_wizard)
# display = QPushButton(_("Display")) # display = QPushButton(_("Display"))
# display.clicked.connect(self.bal_window.preview_modal_dialog) # display.clicked.connect(self.bal_window.preview_modal_dialog)
refresh = QPushButton(_("Refresh")) refresh = QPushButton()
refresh.setIcon(
read_QIcon_from_bytes(
self.bal_window.bal_plugin.read_file("icons/reload.png")
)
)
refresh.clicked.connect(self.check) refresh.clicked.connect(self.check)
widget = QWidget(self) widget = QWidget(self)
@@ -3684,6 +3732,7 @@ class WillExecutorListWidget(MyTreeView):
wout[k] = self.parent.willexecutors_list[k] wout[k] = self.parent.willexecutors_list[k]
self.parent.update_willexecutors(wout) self.parent.update_willexecutors(wout)
self.parent.save_willexecutors()
self.update() self.update()
def get_edit_key_from_coordinate(self, row, col): def get_edit_key_from_coordinate(self, row, col):
@@ -3694,18 +3743,22 @@ class WillExecutorListWidget(MyTreeView):
def delete(self, selected_keys): def delete(self, selected_keys):
for key in selected_keys: for key in selected_keys:
del self.parent.willexecutors_list[key] del self.parent.willexecutors_list[key]
self.parent.save_willexecutors()
self.update() self.update()
def select(self, selected_keys): def select(self, selected_keys):
for wid, w in self.parent.willexecutors_list.items(): for wid, w in self.parent.willexecutors_list.items():
if wid in selected_keys: if wid in selected_keys:
w["selected"] = True w["selected"] = True
self.parent.save_willexecutors()
self.update() self.update()
def deselect(self, selected_keys): def deselect(self, selected_keys):
for wid, w in self.parent.willexecutors_list.items(): for wid, w in self.parent.willexecutors_list.items():
if wid in selected_keys: if wid in selected_keys:
w["selected"] = False w["selected"] = False
self.parent.save_willexecutors()
self.update() self.update()
def on_edited(self, idx, edit_key, *, text): def on_edited(self, idx, edit_key, *, text):
@@ -3882,7 +3935,6 @@ class WillExecutorWidget(QWidget, MessageBoxMixin):
self.will_executor_list_widget.update() self.will_executor_list_widget.update()
def download_list(self, wes=None): def download_list(self, wes=None):
print("download_list")
if not wes: if not wes:
wes = self.willexecutors_list wes = self.willexecutors_list
self.bal_window.download_list(wes, self.save_willexecutors) self.bal_window.download_list(wes, self.save_willexecutors)
@@ -3920,10 +3972,7 @@ class WillExecutorWidget(QWidget, MessageBoxMixin):
return data return data
def save_willexecutors(self, wes=None): def save_willexecutors(self, wes=None):
print("save willexecutors",wes)
if not wes: if not wes:
print("not wes",self.willexecutors_list)
wes = self.willexecutors_list wes = self.willexecutors_list
self.willexecutors_list.update(wes) self.willexecutors_list.update(wes)
self.will_executor_list_widget.update() self.will_executor_list_widget.update()
@@ -3977,9 +4026,16 @@ class CheckAliveError(Exception):
def log_error(exec_info, window=None): def log_error(exec_info, window=None):
_logger.error(exec_info) _logger.error(f"LOG_ERROR: {exec_info}")
#tb = traceback.format_exc()
try:
tb=exec_info[1]
_logger.error(tb)
except Exception:
tb = traceback.format_exc() tb = traceback.format_exc()
_logger.error(tb) _logger.error(tb)
if window is not None: if window is not None:
window.show_error(exec_info) window.show_error(exec_info)
@@ -4011,8 +4067,8 @@ class BalCalendar:
@staticmethod @staticmethod
def write_temp_ics(content): def write_temp_ics(content):
fd, path = tempfile.mkstemp(prefix="event_", suffix=".ics") fd, path = tempfile.mkstemp(prefix="event_", suffix=".ics")
with os.fdopen(fd, "w", encoding="utf-8") as f: with os.fdopen(fd, "wb") as f:
f.write(content) f.write(content.encode("utf-8"))
return path return path
@staticmethod @staticmethod
@@ -4021,11 +4077,6 @@ class BalCalendar:
try: try:
subprocess.check_call([calendar_app, path]) subprocess.check_call([calendar_app, path])
return True return True
except Exception as _e:
_logger.error(f"starting calendar app linux failed:{_e}")
try:
import os
os.startfile(path)
except Exception as e: except Exception as e:
_logger.error(f"starting calendar app {e}") _logger.error(f"starting calendar app {e}")
return False return False
@@ -4039,13 +4090,30 @@ class BalCalendar:
@staticmethod @staticmethod
def ical_escape(text: str) -> str: def ical_escape(text: str) -> str:
# escape per RFC5545: backslash, ; , newlines # escape per RFC5545: backslash, ; , newlines
text = text.encode("utf-8")
text = ( text = (
text.replace("\\", "\\\\") text.replace(b"\\", b"\\\\")
.replace(";", r"\;") .replace(b";", b"\\;")
.replace(",", r"\,") .replace(b",", b"\\,")
.replace("\n", r"\n")
) )
return BalCalendar.fold_ical_line(text) out =""
temp=text.split(b"\r\n")
for s in temp:
encoded= s
cut =0
while len(encoded) >75:
cut+=5
encoded=f"{s[:len(s)-cut]}"
if encoded[-1]==b"\\" and encoded[-2]!=b"\\\\":
cut += 1
encoded=f"{s[:len(s)-cut]}"
encoded=f"{encoded}...\r\n".encode("utf-8")
if cut>0:
out+=str(f"{s[:len(s)-cut].decode()}...\r\n")
else:
out+=str(f"{s.decode()}\r\n")
return out[:-2]
@staticmethod @staticmethod
def fold_ical_line(line: str, limit: int = 75) -> str: def fold_ical_line(line: str, limit: int = 75) -> str:

View File

@@ -274,7 +274,6 @@ class Willexecutors:
@staticmethod @staticmethod
def download_list(old_willexecutors,welist_server): def download_list(old_willexecutors,welist_server):
print("willexecutor download list")
try: try:
welist_server = welist_server if welist_server[-1] == '/' else welist_server+'/' welist_server = welist_server if welist_server[-1] == '/' else welist_server+'/'
willexecutors = Willexecutors.send_request( willexecutors = Willexecutors.send_request(
@@ -282,14 +281,11 @@ class Willexecutors:
f"{welist_server}data/{chainname}?page=0&limit=100", f"{welist_server}data/{chainname}?page=0&limit=100",
) )
# del willexecutors["status"] # del willexecutors["status"]
print("willexecutors",willexecutors)
for w in willexecutors: for w in willexecutors:
print(w)
if w not in ("status", "url"): if w not in ("status", "url"):
Willexecutors.initialize_willexecutor( Willexecutors.initialize_willexecutor(
willexecutors[w], w, None, old_willexecutors.get(w,{}) willexecutors[w], w, None, old_willexecutors.get(w,None)
) )
print("success")
# bal_plugin.WILLEXECUTORS.set(l) # bal_plugin.WILLEXECUTORS.set(l)
# bal_plugin.config.set_key(bal_plugin.WILLEXECUTORS,l,save=True) # bal_plugin.config.set_key(bal_plugin.WILLEXECUTORS,l,save=True)
return willexecutors return willexecutors