diff --git a/bal.py b/bal.py index 1b4c75c..a8fdd9c 100644 --- a/bal.py +++ b/bal.py @@ -82,12 +82,14 @@ class BalPlugin(BasePlugin): self.ALLOW_REPUSH = BalConfig(config, "bal_allow_repush",True) self.FIRST_EXECUTION = BalConfig(config, "bal_first_execution",True) self.WILLEXECUTORS = BalConfig(config, "bal_willexecutors", { - 'https://we.bitcoin-after.life': { - "base_fee": 100000, - "status": "New", - "info":"Bitcoin After Life Will Executor", - "address":"bcrt1qa5cntu4hgadw8zd3n6sq2nzjy34sxdtd9u0gp7", - "selected":True + "mainnet": { + 'https://we.bitcoin-after.life': { + "base_fee": 100000, + "status": "New", + "info":"Bitcoin After Life Will Executor", + "address":"bcrt1qa5cntu4hgadw8zd3n6sq2nzjy34sxdtd9u0gp7", + "selected":True + } } }) self.WILL_SETTINGS = BalConfig(config, "bal_will_settings", { diff --git a/qt.py b/qt.py index 6b6ca4f..3500c56 100644 --- a/qt.py +++ b/qt.py @@ -244,24 +244,18 @@ if TYPE_CHECKING: from electrum.gui.qt.main_window import ElectrumWindow from electrum.gui.qt.util import ( - Buttons, - read_QIcon, - import_meta_gui, - export_meta_gui, - MessageBoxMixin, - Buttons, - export_meta_gui, - MessageBoxMixin, - char_width_in_lineedit, - ColorScheme, Buttons, CancelButton, char_width_in_lineedit, CloseButton, + ColorScheme, EnterButton, + export_meta_gui, HelpButton, + import_meta_gui, MessageBoxMixin, OkButton, + read_QIcon, TaskThread, WindowModalDialog, WWLabel, @@ -418,8 +412,11 @@ class Plugin(BalPlugin,Logger): def settings_widget(self, window): w=self.get_window(window.window) - return EnterButton(_('Settings'), partial(w.settings_dialog,window)) + widget=QWidget() + enterbutton=EnterButton(_('Settings'), partial(w.settings_dialog,window)) + widget.setLayout(Buttons(enterbutton,widget)) + return widget def password_dialog(self, msg=None, parent=None): parent = parent or self d = PasswordDialog(parent, msg) @@ -581,37 +578,56 @@ class BalWindow(Logger): self.bal_plugin.validate_will_settings(self.will_settings) self.heir_list.update_will_settings() - + + def init_wizard(self): + wizard_dialog = BalWizardDialog(self) + wizard_dialog.exec() def show_willexecutor_dialog(self): self.willexecutor_dialog = WillExecutorDialog(self) self.willexecutor_dialog.show() def create_heirs_tab(self): - self.heir_list = l = HeirList(self) + self.heir_list = l = HeirList(self,self.window) tab = self.window.create_list_tab(l) tab.is_shown_cv = shown_cv(True) return tab def create_will_tab(self): - self.will_list = l = PreviewList(self,None) + self.will_list = l = PreviewList(self,self.window,None) tab = self.window.create_list_tab(l) tab.is_shown_cv = shown_cv(True) return tab - def new_heir_dialog(self): + def new_heir_dialog(self,heir=None): d = BalDialog(self.window, self.bal_plugin.get_window_title("New heir")) vbox = QVBoxLayout(d) grid = QGridLayout() heir_name = QLineEdit() heir_name.setFixedWidth(32 * char_width_in_lineedit()) + if heir: + heir_name.setText(heir[0]) heir_address = QLineEdit() heir_address.setFixedWidth(32 * char_width_in_lineedit()) + if heir: + heir_address.setText(heir[1]) heir_amount = PercAmountEdit(self.window.get_decimal_point) + if heir: + heir_amount.setText(heir[2]) heir_locktime = HeirsLockTimeEdit(self.window,0) + if heir: + heir_locktime.setText(heir[3]) heir_is_xpub = QCheckBox() + new_heir_button=QPushButton(_("Add another heir")) + self.add_another_heir=False + def new_heir(): + self.add_another_heir=True + d.accept() + + new_heir_button.clicked.connect(new_heir) + new_heir_button.setDefault(True) grid.addWidget(QLabel(_("Name")), 1, 0) grid.addWidget(heir_name, 1, 1) @@ -626,7 +642,7 @@ class BalWindow(Logger): grid.addWidget(HelpButton("Fixed or Percentage amount if end with %"),3,2) vbox.addLayout(grid) - vbox.addLayout(Buttons(CancelButton(d), OkButton(d))) + vbox.addLayout(Buttons(CancelButton(d), OkButton(d),new_heir_button)) while d.exec(): #TODO SAVE HEIR heir = [ @@ -637,6 +653,8 @@ class BalWindow(Logger): ] try: self.set_heir(heir) + if self.add_another_heir: + self.new_heir_dialog() break except Exception as e: self.show_error(str(e)) @@ -943,8 +961,8 @@ class BalWindow(Logger): def on_close(self): try: if not self.disable_plugin: - close_window=BalCloseDialog(self) - close_window.close_plugin_task() + close_window=BalBuildWillDialog(self) + close_window.build_will_task() self.save_willitems() self.heirs_tab.close() self.will_tab.close() @@ -1440,6 +1458,256 @@ class BalDialog(WindowModalDialog): WindowModalDialog.__init__(self,self.parent,title) self.setWindowIcon(read_bal_QIcon(icon)) +class BalWizardDialog(BalDialog): + def __init__(self,bal_window: 'BalWindow' ): + assert bal_window + BalDialog.__init__(self, bal_window.window, _("Bal Wizard Setup")) + self.setMinimumSize(800, 400) + self.bal_window = bal_window + self.parent = bal_window.window + self.layout=QVBoxLayout(self) + self.widget = BalWizardHeirsWidget(bal_window,self,self.on_next_heir,None,self.on_cancel_heir) + self.layout.addWidget(self.widget) + + def next_widget(self,widget): + self.layout.removeWidget(self.widget) + self.widget.close() + self.widget=widget + self.layout.addWidget(self.widget) + #self.update() + #self.repaint() + + def on_next_heir(self): + self.next_widget(BalWizardLocktimeAndFeeWidget(self.bal_window,self,self.on_next_locktimeandfee,self.on_previous_heir,self.on_cancel_heir)) + + def on_previous_heir(self): + self.next_widget(BalWizardHeirsWidget(self.bal_window,self,self.on_next_heir,None,self.on_cancel_heir)) + + def on_cancel_heir(self): + pass + def on_next_wedonwload(self): + self.next_widget(BalWizardWEWidget(self.bal_window,self,self.on_next_we,self.on_next_locktimeandfee,self.on_cancel_heir)) + def on_next_we(self): + close_window=BalBuildWillDialog(self.bal_window,self) + close_window.build_will_task() + self.close() + #self.next_widget(BalWizardLocktimeAndFeeWidget(self.bal_window,self,self.on_next_locktimeandfee,self.on_next_wedonwload,self.on_next_wedonwload.on_cancel_heir)) + + def on_next_locktimeandfee(self): + self.next_widget(BalWizardWEDownloadWidget(self.bal_window,self,self.on_next_wedonwload,self.on_next_heir,self.on_cancel_heir)) + def on_accept(self): + print("accepted") + def on_reject(self): + print("rejected") + def on_close(self): + print("close") + def closeEvent(self,event): + self.bal_window.update_all() + self.bal_window.heir_list.update_will_settings() + print("close event") + + +class BalWizardWidget(QWidget): + title = None + message = None + def __init__(self,bal_window: 'BalWindow',parent,on_next,on_previous,on_cancel): + QWidget.__init__(self,parent) + self.vbox=QVBoxLayout(self) + self.bal_window=bal_window + self.parent=parent + self.on_next=on_next + self.on_cancel=on_cancel + self.titleLabel = QLabel(self.title) + self.vbox.addWidget(self.titleLabel) + self.messageLabel = QLabel(_(self.message)) + self.vbox.addWidget(self.messageLabel) + + self.content = self.get_content() + self.content_container= QWidget() + self.containrelayout=QVBoxLayout(self.content_container) + self.containrelayout.addWidget(self.content) + + self.vbox.addWidget(self.content_container) + + spacer_widget = QWidget() + spacer_widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + self.vbox.addWidget(spacer_widget) + + self.buttons=[] + if on_previous: + self.on_previous=on_previous + self.previous_button = QPushButton(_("Previous")) + self.previous_button.clicked.connect(self._on_previous) + self.buttons.append(self.previous_button) + + self.next_button = QPushButton(_("Next")) + self.next_button.clicked.connect(self._on_next) + self.buttons.append(self.next_button) + + self.abort_button = QPushButton(_("Cancel")) + self.abort_button.clicked.connect(self._on_cancel) + self.buttons.append(self.abort_button) + + self.vbox.addLayout(Buttons(*self.buttons)) + + def _on_cancel(self): + self.on_cancel() + self.parent.close() + + def _on_next(self): + if self.validate(): + self.on_next() + + def _on_previous(self): + self.on_previous() + + def get_content(self): + pass + + def validate(self): + return True + + +class BalWizardHeirsWidget(BalWizardWidget): + title="Bitcoin After Life Heirs" + message="Please add your heirs\n remember that 100% of wallet balance will be spent" + + + def get_content(self): + self.heirs_list=HeirList(self.bal_window,self.parent) + button_add=QPushButton(_("Add")) + button_add.clicked.connect(self.add_heir) + button_import=QPushButton(_("Import from file")) + button_import.clicked.connect(self.import_from_file) + widget=QWidget() + vbox=QVBoxLayout(widget) + vbox.addWidget(self.heirs_list) + vbox.addLayout(Buttons(button_add,button_import)) + return widget + + + def import_from_file(self): + self.bal_window.import_heirs() + self.heirs_list.update() + def add_heir(self): + self.bal_window.new_heir_dialog() + self.heirs_list.update() + def validate(self): + return True + +class BalWizardWEDownloadWidget(BalWizardWidget): + title=_("Bitcoin After Life Will-Executors") + message=_("Choose willexecutors download method") + + def get_content(self): + question=QLabel() + self.combo=QComboBox() + self.combo.addItems([ + "Automatically download and select willexecutors", + "Only download willexecutors list", + "Import willexecutor list from file", + "Manual"]) + #heir_name.setFixedWidth(32 * char_width_in_lineedit()) + return self.combo + + def validate(self): + return True + def _on_next(self): + index = self.combo.currentIndex() + _logger.debug(f"selected index:{index}") + if index < 2: + willexecutors = Willexecutors.download_list(self.bal_window.bal_plugin) + if index < 1: + for we in willexecutors.values(): + we['selected']=True + + elif index == 2: + #TODO import from file + pass + elif index == 3: + #TODO DO NOTHING + pass + + if self.validate(): + return self.on_next() + +class BalWizardWEWidget(BalWizardWidget): + title=("Bitcoin After Life Will-Executors") + message=_("Configure and select your willexecutors") + + def get_content(self): + widget=QWidget() + vbox=QVBoxLayout(widget) + vbox.addWidget(WillExecutorWidget(self,self.bal_window,Willexecutors.get_willexecutors(self.bal_window.bal_plugin))) + return widget + +class BalWizardLocktimeAndFeeWidget(BalWizardWidget): + title=("Bitcoin After Life Will Settings") + message=_("") + + def get_content(self): + widget=QWidget() + self.heir_locktime = HeirsLockTimeEdit(widget,0) + will_settings=self.bal_window.bal_plugin.WILL_SETTINGS.get() + self.heir_locktime.set_locktime(will_settings['locktime']) + def on_heir_locktime(): + if not self.heir_locktime.get_locktime(): + self.heir_locktime.set_locktime('1y') + self.bal_window.will_settings['locktime'] = self.heir_locktime.get_locktime() if self.heir_locktime.get_locktime() else "1y" + self.bal_window.bal_plugin.WILL_SETTINGS.set(self.bal_window.will_settings) + self.heir_locktime.valueEdited.connect(on_heir_locktime) + + self.heir_threshold = HeirsLockTimeEdit(widget,0) + self.heir_threshold.set_locktime(will_settings['threshold']) + def on_heir_threshold(): + if not self.heir_threshold.get_locktime(): + self.heir_threshold.set_locktime('180d') + + self.bal_window.will_settings['threshold'] = self.heir_threshold.get_locktime() + self.bal_window.bal_plugin.WILL_SETTINGS.set(self.bal_window.will_settings) + self.heir_threshold.valueEdited.connect(on_heir_threshold) + + self.heir_tx_fees = QSpinBox(widget) + + self.heir_tx_fees.setMinimum(1) + self.heir_tx_fees.setMaximum(10000) + self.heir_tx_fees.setValue(will_settings['tx_fees']) + def on_heir_tx_fees(): + if not self.heir_tx_fees.value(): + self.heir_tx_fees.set_value(1) + self.bal_window.will_settings['tx_fees'] = self.heir_tx_fees.value() + self.bal_window.bal_plugin.WILL_SETTINGS.set(self.bal_window.will_settings) + self.heir_tx_fees.valueChanged.connect(on_heir_tx_fees) + + def make_hlayout(label,twidget,help_text): + tw=QWidget() + hlayout=QHBoxLayout(tw) + hlayout.addWidget(QLabel(label)) + hlayout.addWidget(twidget) + hlayout.addWidget(HelpButton(help_text)) + return tw + + + layout = QVBoxLayout(widget) + + layout.addWidget(make_hlayout(_("Delivery Time:"),self.heir_locktime,_("Locktime* to be used in the transaction\n" + +"if you choose Raw, you can insert various options based on suffix:\n" + +" - d: number of days after current day(ex: 1d means tomorrow)\n" + +" - y: number of years after currrent day(ex: 1y means one year from today)\n" + +"* locktime can be anticipated to update will\n"))) + layout.addWidget(make_hlayout(_("Check Alive:"),self.heir_threshold,_("Check to ask for invalidation.\n" + +"When less then this time is missing, ask to invalidate.\n" + +"If you fail to invalidate during this time, your transactions will be delivered to your heirs.\n" + +"if you choose Raw, you can insert various options based on suffix:\n" + +" - d: number of days after current day(ex: 1d means tomorrow).\n" + +" - y: number of years after currrent day(ex: 1y means one year from today).\n\n"))) + layout.addWidget(make_hlayout(_("Fees(sats/vbyte):"),self.heir_tx_fees,("Fee to be used in the transaction"))) + + spacer_widget = QWidget() + spacer_widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + layout.addWidget(spacer_widget) + return widget + class BalWaitingDialog(BalDialog): updatemessage=pyqtSignal([str], arguments=['message']) def __init__(self, bal_window: 'BalWindow', message: str, task, on_success=None, on_error=None, on_cancel=None,exe=True): @@ -1523,13 +1791,15 @@ class bal_checkbox(QCheckBox): -class BalCloseDialog(BalDialog): +class BalBuildWillDialog(BalDialog): updatemessage=pyqtSignal() - def __init__(self,bal_window): - BalDialog.__init__(self,bal_window.window,"Closing BAL") + def __init__(self,bal_window,parent=None): + if not parent: + parent = bal_window.window + BalDialog.__init__(self,parent,"Building Will") self.updatemessage.connect(self.update) self.bal_window=bal_window - self.message_label = QLabel("Closing BAL:") + self.message_label = QLabel("Building Will:") self.vbox = QVBoxLayout(self) self.vbox.addWidget(self.message_label) self.qwidget=QWidget() @@ -1547,8 +1817,8 @@ class BalCloseDialog(BalDialog): def task_finished(self): pass - def close_plugin_task(self): - _logger.debug("close task to be started") + def build_will_task(self): + _logger.debug("build will task to be started") self.thread.add(self.task_phase1,on_success=self.on_success_phase1,on_done=self.on_accept,on_error=self.on_error_phase1) self.show() self.exec() @@ -1713,7 +1983,7 @@ class BalCloseDialog(BalDialog): self.msg_set_invalidating() #need to sign invalidate and restart phase 1 - password = self.bal_window.get_wallet_password("Invalidate your old will",parent=self.bal_window.window) + password = self.bal_window.get_wallet_password("Invalidate your old will",parent=self) if password is False: self.msg_set_invalidating("Aborted") self.wait(3) @@ -1724,7 +1994,7 @@ class BalCloseDialog(BalDialog): return elif self.have_to_sign: - password = self.bal_window.get_wallet_password("Sign your will",parent=self.bal_window.window) + password = self.bal_window.get_wallet_password("Sign your will",parent=self) if password is False: self.msg_set_signing('Aborted') else: @@ -1739,6 +2009,7 @@ class BalCloseDialog(BalDialog): self.close() def closeEvent(self,event): + self.bal_window.update_all() self._stopping=True self.thread.stop() @@ -1868,16 +2139,16 @@ class HeirList(MyTreeView,MessageBoxMixin): ROLE_HEIR_KEY = Qt.ItemDataRole.UserRole + 1001 key_role = ROLE_HEIR_KEY - def __init__(self, bal_window: 'BalWindow'): + def __init__(self, bal_window: 'BalWindow',parent): super().__init__( - parent=bal_window.window, + parent=parent, main_window=bal_window.window, stretch_column=self.Columns.NAME, editable_columns=[self.Columns.NAME,self.Columns.ADDRESS,self.Columns.AMOUNT], ) self.decimal_point = bal_window.bal_plugin.config.get_decimal_point() self.bal_window = bal_window - + try: self.setModel(QStandardItemModel(self)) self.sortByColumn(self.Columns.NAME, Qt.SortOrder.AscendingOrder) @@ -1939,6 +2210,12 @@ class HeirList(MyTreeView,MessageBoxMixin): menu.addAction(_("Delete"), lambda: self.bal_window.delete_heirs(selected_keys)) menu.exec(self.viewport().mapToGlobal(position)) + #def get_selected_keys(self): + # selected_keys = [] + # for s_idx in self.selected_in_column(self.Columns.NAME): + # sel_key = self.model().itemFromIndex(s_idx).data(0) + # selected_keys.append(sel_key) + # return selected_keys def update(self): if self.maybe_defer_update(): return @@ -1970,6 +2247,7 @@ class HeirList(MyTreeView,MessageBoxMixin): # FIXME refresh loses sort order; so set "default" here: self.filter() run_hook('update_heirs_tab', self) + self.update_will_settings() def refresh_row(self, key, row): # nothing to update here @@ -1984,12 +2262,12 @@ class HeirList(MyTreeView,MessageBoxMixin): menu.addAction(_("Import"), self.bal_window.import_heirs) menu.addAction(_("Export"), lambda: self.bal_window.export_heirs()) - self.heir_locktime = HeirsLockTimeEdit(self.window(),0) + self.heir_locktime = HeirsLockTimeEdit(self,0) def on_heir_locktime(): if not self.heir_locktime.get_locktime(): self.heir_locktime.set_locktime('1y') self.bal_window.will_settings['locktime'] = self.heir_locktime.get_locktime() if self.heir_locktime.get_locktime() else "1y" - self.bal_window.bal_plugin.config.set_key('will_settings',self.bal_window.will_settings,save = True) + self.bal_window.bal_plugin.WILL_SETTINGS.set(self.bal_window.will_settings) self.heir_locktime.valueEdited.connect(on_heir_locktime) self.heir_threshold = HeirsLockTimeEdit(self,0) @@ -1998,7 +2276,7 @@ class HeirList(MyTreeView,MessageBoxMixin): self.heir_threshold.set_locktime('180d') self.bal_window.will_settings['threshold'] = self.heir_threshold.get_locktime() - self.bal_window.bal_plugin.config.set_key('will_settings',self.bal_window.will_settings,save = True) + self.bal_window.bal_plugin.WILL_SETTINGS.set(self.bal_window.will_settings) self.heir_threshold.valueEdited.connect(on_heir_threshold) self.heir_tx_fees = QSpinBox() @@ -2008,7 +2286,7 @@ class HeirList(MyTreeView,MessageBoxMixin): if not self.heir_tx_fees.value(): self.heir_tx_fees.set_value(1) self.bal_window.will_settings['tx_fees'] = self.heir_tx_fees.value() - self.bal_window.bal_plugin.config.set_key('will_settings',self.bal_window.will_settings,save = True) + self.bal_window.bal_plugin.WILL_SETTINGS.set(self.bal_window.will_settings) self.heir_tx_fees.valueChanged.connect(on_heir_tx_fees) @@ -2047,16 +2325,18 @@ class HeirList(MyTreeView,MessageBoxMixin): return toolbar def update_will_settings(self): - self.heir_threshold.set_locktime(self.bal_window.will_settings['threshold']) - self.heir_locktime.set_locktime(self.bal_window.will_settings['locktime']) - self.heir_tx_fees.setValue(int(self.bal_window.will_settings['tx_fees'])) + try: + self.heir_locktime.set_locktime(self.bal_window.will_settings['locktime']) + self.heir_tx_fees.setValue(int(self.bal_window.will_settings['tx_fees'])) + self.heir_threshold.set_locktime(self.bal_window.will_settings['threshold']) + + except Exception as e: + print("Exception update_will_settings",e) def build_transactions(self): will = self.bal_window.prepare_will() - - class PreviewList(MyTreeView): class Columns(MyTreeView.BaseColumnsEnum): LOCKTIME = enum.auto() @@ -2074,12 +2354,14 @@ class PreviewList(MyTreeView): ROLE_HEIR_KEY = Qt.ItemDataRole.UserRole + 2000 key_role = ROLE_HEIR_KEY - def __init__(self, parent: 'BalWindow',will): + def __init__(self, bal_window: 'BalWindow',parent,will): super().__init__( - parent=parent.window, + parent=parent, stretch_column=self.Columns.TXID, ) - self.decimal_point=parent.bal_plugin.config.get_decimal_point + self.parent=parent + self.bal_window=bal_window + self.decimal_point=bal_window.bal_plugin.config.get_decimal_point self.setModel(QStandardItemModel(self)) self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) @@ -2087,14 +2369,13 @@ class PreviewList(MyTreeView): if not will is None: self.will = will else: - self.will = parent.willitems + self.will = bal_window.willitems - self.bal_window = parent - self.wallet=parent.window.wallet + self.wallet=bal_window.window.wallet self.setModel(QStandardItemModel(self)) self.setSortingEnabled(True) self.std_model = self.model() - self.config = parent.bal_plugin.config + self.config = bal_window.bal_plugin.config self.bal_plugin=self.bal_window.bal_plugin self.update() @@ -2120,6 +2401,7 @@ class PreviewList(MyTreeView): menu.exec(self.viewport().mapToGlobal(position)) + def delete(self,selected_keys): for key in selected_keys: del self.will[key] @@ -2222,6 +2504,10 @@ class PreviewList(MyTreeView): menu.addAction(_("Broadcast"), self.broadcast) menu.addAction(_("Check"), self.check) menu.addAction(_("Invalidate"), self.invalidate_will) + + wizard=QPushButton(_("Setup Wizard")) + wizard.clicked.connect(self.bal_window.init_wizard) + prepareButton = QPushButton(_("Prepare")) prepareButton.clicked.connect(self.build_transactions) signButton = QPushButton(_("Sign")) @@ -2232,6 +2518,7 @@ class PreviewList(MyTreeView): displayButton.clicked.connect(self.bal_window.preview_modal_dialog) hlayout = QHBoxLayout() widget = QWidget() + hlayout.addWidget(wizard) hlayout.addWidget(prepareButton) hlayout.addWidget(signButton) hlayout.addWidget(pushButton) @@ -2358,9 +2645,8 @@ def read_bal_QPixmap(icon_basename: str=DEFAULT_ICON) -> QPixmap: return QPixmap(icon_path(icon_basename)) + class WillDetailDialog(BalDialog): - - def __init__(self, bal_window): self.will = bal_window.willitems @@ -2686,22 +2972,34 @@ class WillExecutorList(MyTreeView): _logger.error(e) -class WillExecutorDialog(BalDialog,MessageBoxMixin): - def __init__(self, bal_window): - BalDialog.__init__(self,bal_window.window) - self.bal_plugin = bal_window.bal_plugin - self.config = self.bal_plugin.config - self.window = bal_window.window - self.bal_window = bal_window - self.willexecutors_list = Willexecutors.get_willexecutors(self.bal_plugin) +class WillExecutorWidget(QWidget,MessageBoxMixin): + def __init__(self,parent,bal_window,willexecutors=None): + self.bal_window=bal_window + self.bal_plugin=bal_window.bal_plugin + self.parent=parent + MessageBoxMixin.__init__(self) + QWidget.__init__(self,parent) + if willexecutors: + self.willexecutors_list=willexecutors + else: + self.willexecutors_list = Willexecutors.get_willexecutors(self.bal_plugin) - self.setWindowTitle(_('Will-Executor Service List')) - self.setMinimumSize(1000, 200) self.size_label = QLabel() self.willexecutor_list = WillExecutorList(self) vbox = QVBoxLayout(self) vbox.addWidget(self.size_label) + + widget = QWidget() + hbox=QHBoxLayout(widget) + hbox.addWidget(QLabel(_("Add transactions without willexecutor"))) + heir_no_willexecutor = bal_checkbox(self.bal_plugin.NO_WILLEXECUTOR) + hbox.addWidget(heir_no_willexecutor) + spacer_widget = QWidget() + spacer_widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + hbox.addWidget(spacer_widget) + vbox.addWidget(widget) + vbox.addWidget(self.willexecutor_list) buttonbox = QHBoxLayout() @@ -2725,14 +3023,8 @@ class WillExecutorDialog(BalDialog,MessageBoxMixin): b.clicked.connect(self.add) buttonbox.addWidget(b) - b = QPushButton(_('Close')) - b.clicked.connect(self.close) - buttonbox.addWidget(b) - vbox.addLayout(buttonbox) - self.willexecutor_list.update() - def add(self): self.willexecutors_list["http://localhost:8080"]={"info":"New Will Executor","base_fee":0,"status":"-1"} self.willexecutor_list.update() @@ -2740,13 +3032,13 @@ class WillExecutorDialog(BalDialog,MessageBoxMixin): self.willexecutors_list.update(Willexecutors.download_list(self.bal_plugin) ) self.willexecutor_list.update() def export_file(self, path): - Util.export_meta_gui(self, _('willexecutors.json'), self.export_json_file) + Util.export_meta_gui(self.bal_window.window, _('willexecutors.json'), self.export_json_file) def export_json_file(self,path): write_json_file(path, self.willexecutors_list) def import_file(self): - import_meta_gui(self, _('willexecutors.json'), self.import_json_file, self.willexecutors_list.update) + import_meta_gui(self.bal_window.window, _('willexecutors.json'), self.import_json_file, self.willexecutors_list.update) def update_willexecutors(self,wes=None): if not wes: @@ -2767,6 +3059,26 @@ class WillExecutorDialog(BalDialog,MessageBoxMixin): def _validate(self,data): return data + def save_willexecutors(self): + Willexecutors.save(self.bal_window.bal_plugin, self.willexecutors_list) + +class WillExecutorDialog(BalDialog,MessageBoxMixin): + def __init__(self, bal_window): + BalDialog.__init__(self,bal_window.window) + self.bal_plugin = bal_window.bal_plugin + self.config = self.bal_plugin.config + self.window = bal_window.window + self.bal_window = bal_window + self.willexecutors_list = Willexecutors.get_willexecutors(self.bal_plugin) + + self.setWindowTitle(_('Will-Executor Service List')) + self.setMinimumSize(1000, 200) + + vbox = QVBoxLayout(self) + vbox.addWidget(WillExecutorWidget(self,self.bal_window,self.willexecutors_list)) + + + def is_hidden(self): return self.isMinimized() or self.isHidden() @@ -2783,6 +3095,4 @@ class WillExecutorDialog(BalDialog,MessageBoxMixin): def closeEvent(self, event): event.accept() - def save_willexecutors(self): - self.bal_plugin.WILLEXECUTORS.set(self.willexecutors_list) diff --git a/willexecutors.py b/willexecutors.py index 76d8f5f..b7350b2 100644 --- a/willexecutors.py +++ b/willexecutors.py @@ -14,12 +14,20 @@ from .util import Util DEFAULT_TIMEOUT = 5 _logger = get_logger(__name__) class Willexecutors: + + def save(bal_plugin, willexecutors): + aw=bal_plugin.WILLEXECUTORS.get() + aw[constants.net.NET_NAME]=willexecutors + print("save",aw) + bal_plugin.WILLEXECUTORS.set(aw) + def get_willexecutors(bal_plugin, update = False,bal_window=False,force=False,task=True): willexecutors = bal_plugin.WILLEXECUTORS.get() + willexecutors=willexecutors.get(constants.net.NET_NAME,{}) for w in willexecutors: Willexecutors.initialize_willexecutor(willexecutors[w],w) - bal = bal_plugin.WILLEXECUTORS.default + bal = bal_plugin.WILLEXECUTORS.default.get(constants.net.NET_NAME,{}) for bal_url,bal_executor in bal.items(): if not bal_url in willexecutors: _logger.debug(f"force add {bal_url} willexecutor") @@ -33,17 +41,16 @@ class Willexecutors: if bal_plugin.PING_WILLEXECUTORS.get() or force: ping_willexecutors = True if bal_plugin.ASK_PING_WILLEXECUTORS.get() and not force: - ping_willexecutors = bal_window.window.question(_("Contact willexecutors servers to update payment informations?")) + if bal_window: + ping_willexecutors = bal_window.window.question(_("Contact willexecutors servers to update payment informations?")) + if ping_willexecutors: if task: bal_window.ping_willexecutors(willexecutors) else: bal_window.ping_willexecutors_task(willexecutors) - return willexecutors - def get_willexecutors_as_sorted_list(bal_plugin,update=False,bal_window=False,force=False,task=True): - willexecutors=Willexecutors.get_willexecutors(bal_plugin,update,bal_window,force,task) - return sorted(willexecutors,key=lambda w:w[1].get('sort',0)) - + w_sorted = dict(sorted(willexecutors.items(), key=lambda w:w[1].get('sort',0),reverse=True)) + return w_sorted def is_selected(willexecutor,value=None): if not willexecutor: return False @@ -185,6 +192,7 @@ class Willexecutors: if not status is None: willexecutor['status'] = status willexecutor['selected'] = Willexecutors.is_selected(willexecutor,selected) + def download_list(bal_plugin): try: l = Willexecutors.send_request('get',"https://welist.bitcoin-after.life/data/bitcoin?page=0&limit=100") @@ -192,8 +200,10 @@ class Willexecutors: for w in l: willexecutor=l[w] Willexecutors.initialize_willexecutor(willexecutor,w,'New',False) - bal_plugin.config.set_key(bal_plugin.WILLEXECUTORS,l,save=True) + #bal_plugin.WILLEXECUTORS.set(l) + #bal_plugin.config.set_key(bal_plugin.WILLEXECUTORS,l,save=True) return l + except Exception as e: _logger.error(f"error downloading willexecutors list:{e}") return {} @@ -204,7 +214,7 @@ class Willexecutors: for w in willexecutors: willexecutor=willexecutors[w] Willexecutors.initialize_willexecutor(willexecutor,w,'New',False) - bal_plugin.config.set_key(bal_plugin.WILLEXECUTORS,willexecutors,save=True) + #bal_plugin.WILLEXECUTORS.set(willexecutors) return h except Exception as e: _logger.error(f"error opening willexecutors json: {e}")