forked from bitcoinafterlife/bal-electrum-plugin
Compare commits
4 Commits
fix/balbui
...
d613438800
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d613438800 | ||
|
|
a27df11dfa | ||
|
|
686c11080f | ||
|
|
be38c9b589 |
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "BAL",
|
"name": "BAL",
|
||||||
"fullname": "Bitcoin After Life",
|
"fullname": "Bitcoin After Life",
|
||||||
"description": "Provides free and decentralized inheritance support<br> Version: 0.2.10",
|
"description": "Provides free and decentralized inheritance support<br> Version: 0.2.7",
|
||||||
"author":"Svatantrya",
|
"author":"Svatantrya",
|
||||||
"available_for": ["qt"],
|
"available_for": ["qt"],
|
||||||
"icon":"icons/bal32x32.png"
|
"icon":"icons/bal32x32.png"
|
||||||
|
|||||||
726
qt.py
726
qt.py
@@ -390,26 +390,6 @@ class shown_cv:
|
|||||||
|
|
||||||
|
|
||||||
class BalWindow(Logger):
|
class BalWindow(Logger):
|
||||||
"""Main application window for Bitcoin After Life inheritance management.
|
|
||||||
|
|
||||||
This class provides the primary UI for:
|
|
||||||
- Managing inheritance plans
|
|
||||||
- Building Wills
|
|
||||||
- Handling heir configurations
|
|
||||||
- Network operations
|
|
||||||
- Transaction signing and broadcasting
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
bal_plugin (BalPlugin): Reference to the plugin instance
|
|
||||||
config (dict): Application configuration
|
|
||||||
network (Network): Network interface
|
|
||||||
wallet (Abstract_Wallet): Wallet interface
|
|
||||||
heirs (list): List of heir configurations
|
|
||||||
will (Will): Current Will being managed
|
|
||||||
building_will (bool): Flag indicating Will construction in progress
|
|
||||||
stop_build (bool): Flag to stop Will construction
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, bal_plugin: "BalPlugin", window: "ElectrumWindow"):
|
def __init__(self, bal_plugin: "BalPlugin", window: "ElectrumWindow"):
|
||||||
Logger.__init__(self)
|
Logger.__init__(self)
|
||||||
self.bal_plugin = bal_plugin
|
self.bal_plugin = bal_plugin
|
||||||
@@ -1291,411 +1271,40 @@ class _LockTimeEditor:
|
|||||||
return cls.min_allowed_value <= x <= cls.max_allowed_value
|
return cls.min_allowed_value <= x <= cls.max_allowed_value
|
||||||
|
|
||||||
|
|
||||||
class HeirsLockTimeEdit(QWidget, _LockTimeEditor):
|
<<<<<<< HEAD
|
||||||
"""HeirsLockTimeEdit class for Bitcoin After Life.
|
=======
|
||||||
|
"""
|
||||||
|
BalWizardDialog - A custom QDialog that implements a multi-step wizard interface.
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
This dialog provides a structured, step-by-step workflow for complex operations
|
||||||
|
in the Bal Electrum plugin, guiding users through a sequence of pages with
|
||||||
|
forward/backward navigation and validation.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- Multi-page navigation with Previous/Next buttons
|
||||||
|
- Automatic validation before proceeding to next page
|
||||||
|
- Progress tracking with visual indicators
|
||||||
|
- Customizable page flow and validation rules
|
||||||
|
- Integration with BalDialog base class for consistent styling
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
The wizard follows a standard pattern:
|
||||||
|
1. Initialize with a list of page constructors
|
||||||
|
2. Each page is responsible for its own setup and validation
|
||||||
|
3. The dialog manages navigation and state between pages
|
||||||
|
4. Finalize action is triggered when all pages are completed
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
See class implementation for attributes
|
pages (list): List of page constructors for the wizard
|
||||||
|
current_page (int): Index of the currently displayed page
|
||||||
|
page_widgets (list): List of instantiated page widgets
|
||||||
|
|
||||||
Example:
|
Args:
|
||||||
instance = HeirsLockTimeEdit(required parameters)
|
parent: Optional parent QWidget
|
||||||
|
title (str): Title to display in the dialog header
|
||||||
|
pages (list): List of page constructors (callables) for each step
|
||||||
"""
|
"""
|
||||||
|
|
||||||
valueEdited = pyqtSignal()
|
|
||||||
locktime_threshold = 50000000
|
|
||||||
|
|
||||||
def __init__(self, parent=None, default_index=1):
|
|
||||||
QWidget.__init__(self, parent)
|
|
||||||
|
|
||||||
hbox = QHBoxLayout()
|
|
||||||
self.setLayout(hbox)
|
|
||||||
hbox.setContentsMargins(0, 0, 0, 0)
|
|
||||||
hbox.setSpacing(0)
|
|
||||||
|
|
||||||
self.locktime_raw_e = LockTimeRawEdit(self, time_edit=self)
|
|
||||||
self.locktime_date_e = LockTimeDateEdit(self, time_edit=self)
|
|
||||||
self.editors = [self.locktime_raw_e, self.locktime_date_e]
|
|
||||||
|
|
||||||
self.combo = QComboBox()
|
|
||||||
options = [_("Raw"), _("Date")]
|
|
||||||
self.option_index_to_editor_map = {
|
|
||||||
0: self.locktime_raw_e,
|
|
||||||
1: self.locktime_date_e,
|
|
||||||
}
|
|
||||||
self.combo.addItems(options)
|
|
||||||
|
|
||||||
self.editor = self.option_index_to_editor_map[default_index]
|
|
||||||
self.combo.currentIndexChanged.connect(self.on_current_index_changed)
|
|
||||||
self.combo.setCurrentIndex(default_index)
|
|
||||||
self.on_current_index_changed(default_index)
|
|
||||||
|
|
||||||
hbox.addWidget(self.combo)
|
|
||||||
for w in self.editors:
|
|
||||||
hbox.addWidget(w)
|
|
||||||
hbox.addStretch(1)
|
|
||||||
# spacer_widget = QWidget()
|
|
||||||
# spacer_widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
|
||||||
# hbox.addWidget(spacer_widget)
|
|
||||||
|
|
||||||
self.locktime_raw_e.editingFinished.connect(self.valueEdited.emit)
|
|
||||||
self.locktime_date_e.dateTimeChanged.connect(self.valueEdited.emit)
|
|
||||||
self.combo.currentIndexChanged.connect(self.valueEdited.emit)
|
|
||||||
|
|
||||||
def on_current_index_changed(self, i):
|
|
||||||
for w in self.editors:
|
|
||||||
w.setVisible(False)
|
|
||||||
w.setEnabled(False)
|
|
||||||
prev_locktime = self.editor.get_locktime()
|
|
||||||
self.editor = self.option_index_to_editor_map[i]
|
|
||||||
if self.editor.is_acceptable_locktime(prev_locktime):
|
|
||||||
self.editor.set_locktime(prev_locktime, force=True)
|
|
||||||
self.editor.setVisible(True)
|
|
||||||
self.editor.setEnabled(True)
|
|
||||||
|
|
||||||
def get_locktime(self) -> Optional[str]:
|
|
||||||
return self.editor.get_locktime()
|
|
||||||
|
|
||||||
def set_index(self, index):
|
|
||||||
self.combo.setCurrentIndex(index)
|
|
||||||
self.on_current_index_changed(index)
|
|
||||||
|
|
||||||
def set_locktime(self, x: Any, force=True) -> None:
|
|
||||||
self.editor.set_locktime(x, force)
|
|
||||||
|
|
||||||
|
|
||||||
"""LockTimeRawEdit class for Bitcoin After Life.
|
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
See class implementation for attributes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
instance = LockTimeRawEdit(required parameters)
|
|
||||||
"""
|
|
||||||
|
|
||||||
class LockTimeRawEdit(QLineEdit, _LockTimeEditor):
|
|
||||||
def __init__(self, parent=None, time_edit=None):
|
|
||||||
QLineEdit.__init__(self, parent)
|
|
||||||
self.setFixedWidth(14 * char_width_in_lineedit())
|
|
||||||
self.textChanged.connect(self.numbify)
|
|
||||||
self.isdays = False
|
|
||||||
self.isyears = False
|
|
||||||
self.isblocks = False
|
|
||||||
self.time_edit = time_edit
|
|
||||||
|
|
||||||
def replace_str(self, text):
|
|
||||||
return str(text).replace("d", "").replace("y", "").replace("b", "")
|
|
||||||
|
|
||||||
def checkbdy(self, s, pos, appendix):
|
|
||||||
try:
|
|
||||||
charpos = pos - 1
|
|
||||||
charpos = max(0, charpos)
|
|
||||||
charpos = min(len(s) - 1, charpos)
|
|
||||||
if appendix == s[charpos]:
|
|
||||||
s = self.replace_str(s) + appendix
|
|
||||||
pos = charpos
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
return pos, s
|
|
||||||
|
|
||||||
def numbify(self):
|
|
||||||
text = self.text().strip()
|
|
||||||
# chars = '0123456789bdy' removed the option to choose locktime by block
|
|
||||||
chars = "0123456789dy"
|
|
||||||
pos = self.cursorPosition()
|
|
||||||
pos = len("".join([i for i in text[:pos] if i in chars]))
|
|
||||||
s = "".join([i for i in text if i in chars])
|
|
||||||
self.isdays = False
|
|
||||||
self.isyears = False
|
|
||||||
self.isblocks = False
|
|
||||||
|
|
||||||
pos, s = self.checkbdy(s, pos, "d")
|
|
||||||
pos, s = self.checkbdy(s, pos, "y")
|
|
||||||
pos, s = self.checkbdy(s, pos, "b")
|
|
||||||
|
|
||||||
if "d" in s:
|
|
||||||
self.isdays = True
|
|
||||||
if "y" in s:
|
|
||||||
self.isyears = True
|
|
||||||
if "b" in s:
|
|
||||||
self.isblocks = True
|
|
||||||
|
|
||||||
if self.isdays:
|
|
||||||
s = self.replace_str(s) + "d"
|
|
||||||
if self.isyears:
|
|
||||||
s = self.replace_str(s) + "y"
|
|
||||||
if self.isblocks:
|
|
||||||
s = self.replace_str(s) + "b"
|
|
||||||
|
|
||||||
self.set_locktime(s, force=False)
|
|
||||||
# setText sets Modified to False. Instead we want to remember
|
|
||||||
# if updates were because of user modification.
|
|
||||||
self.setModified(self.hasFocus())
|
|
||||||
self.setCursorPosition(pos)
|
|
||||||
|
|
||||||
def get_locktime(self) -> Optional[str]:
|
|
||||||
try:
|
|
||||||
return str(self.text())
|
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def set_locktime(self, x: Any, force=True) -> None:
|
|
||||||
out = str(x)
|
|
||||||
if "d" in out:
|
|
||||||
out = self.replace_str(x) + "d"
|
|
||||||
elif "y" in out:
|
|
||||||
out = self.replace_str(x) + "y"
|
|
||||||
elif "b" in out:
|
|
||||||
out = self.replace_str(x) + "b"
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
out = int(x)
|
|
||||||
except Exception:
|
|
||||||
self.setText("")
|
|
||||||
return
|
|
||||||
out = max(out, self.min_allowed_value)
|
|
||||||
out = min(out, self.max_allowed_value)
|
|
||||||
self.setText(str(out))
|
|
||||||
|
|
||||||
"""LockTimeHeightEdit class for Bitcoin After Life.
|
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
See class implementation for attributes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
instance = LockTimeHeightEdit(required parameters)
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class LockTimeHeightEdit(LockTimeRawEdit):
|
|
||||||
max_allowed_value = NLOCKTIME_BLOCKHEIGHT_MAX
|
|
||||||
|
|
||||||
def __init__(self, parent=None, time_edit=None):
|
|
||||||
LockTimeRawEdit.__init__(self, parent)
|
|
||||||
self.setFixedWidth(20 * char_width_in_lineedit())
|
|
||||||
self.time_edit = time_edit
|
|
||||||
|
|
||||||
def paintEvent(self, event):
|
|
||||||
super().paintEvent(event)
|
|
||||||
panel = QStyleOptionFrame()
|
|
||||||
self.initStyleOption(panel)
|
|
||||||
textRect = self.style().subElementRect(QStyle.SE_LineEditContents, panel, self)
|
|
||||||
textRect.adjust(2, 0, -10, 0)
|
|
||||||
painter = QPainter(self)
|
|
||||||
painter.setPen(ColorScheme.GRAY.as_color())
|
|
||||||
painter.drawText(textRect, int(Qt.AlignRight | Qt.AlignVCenter), "height")
|
|
||||||
|
|
||||||
|
|
||||||
def get_max_allowed_timestamp() -> int:
|
|
||||||
ts = NLOCKTIME_MAX
|
|
||||||
# Test if this value is within the valid timestamp limits (which is platform-dependent).
|
|
||||||
# see #6170
|
|
||||||
try:
|
|
||||||
datetime.fromtimestamp(ts)
|
|
||||||
except (OSError, OverflowError):
|
|
||||||
ts = 2**31 - 1 # INT32_MAX
|
|
||||||
datetime.fromtimestamp(ts) # test if raises
|
|
||||||
return ts
|
|
||||||
"""LockTimeDateEdit class for Bitcoin After Life.
|
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
See class implementation for attributes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
instance = LockTimeDateEdit(required parameters)
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class LockTimeDateEdit(QDateTimeEdit, _LockTimeEditor):
|
|
||||||
min_allowed_value = NLOCKTIME_BLOCKHEIGHT_MAX + 1
|
|
||||||
max_allowed_value = get_max_allowed_timestamp()
|
|
||||||
|
|
||||||
def __init__(self, parent=None, time_edit=None):
|
|
||||||
QDateTimeEdit.__init__(self, parent)
|
|
||||||
self.setMinimumDateTime(datetime.fromtimestamp(self.min_allowed_value))
|
|
||||||
self.setMaximumDateTime(datetime.fromtimestamp(self.max_allowed_value))
|
|
||||||
self.setDateTime(QDateTime.currentDateTime())
|
|
||||||
self.time_edit = time_edit
|
|
||||||
|
|
||||||
def get_locktime(self) -> Optional[int]:
|
|
||||||
dt = self.dateTime().toPyDateTime()
|
|
||||||
locktime = int(time.mktime(dt.timetuple()))
|
|
||||||
return locktime
|
|
||||||
|
|
||||||
def set_locktime(self, x: Any, force=False) -> None:
|
|
||||||
if not self.is_acceptable_locktime(x):
|
|
||||||
self.setDateTime(QDateTime.currentDateTime())
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
x = int(x)
|
|
||||||
except Exception:
|
|
||||||
self.setDateTime(QDateTime.currentDateTime())
|
|
||||||
return
|
|
||||||
dt = datetime.fromtimestamp(x)
|
|
||||||
self.setDateTime(dt)
|
|
||||||
|
|
||||||
|
|
||||||
"""Widget for editing percentage amounts.
|
|
||||||
|
|
||||||
Extends BTCAmountEdit to provide:
|
|
||||||
- Percentage-based input (0-100%)
|
|
||||||
- Validation of percentage values
|
|
||||||
- Conversion between percentage and satoshis
|
|
||||||
- Formatting for display
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
min_value (float): Minimum percentage (default 0.0)
|
|
||||||
max_value (float): Maximum percentage (default 100.0)
|
|
||||||
step (float): Increment step for percentage values
|
|
||||||
|
|
||||||
Methods:
|
|
||||||
value(): Return current percentage as float
|
|
||||||
setValue(): Set percentage value
|
|
||||||
validate(): Validate percentage range
|
|
||||||
"""
|
|
||||||
|
|
||||||
_NOT_GIVEN = object() # sentinel value
|
|
||||||
|
|
||||||
|
|
||||||
class PercAmountEdit(BTCAmountEdit):
|
|
||||||
def __init__(
|
|
||||||
self, decimal_point, is_int=False, parent=None, *, max_amount=_NOT_GIVEN
|
|
||||||
):
|
|
||||||
super().__init__(decimal_point, is_int, parent, max_amount=max_amount)
|
|
||||||
|
|
||||||
def numbify(self):
|
|
||||||
text = self.text().strip()
|
|
||||||
if text == "!":
|
|
||||||
self.shortcut.emit()
|
|
||||||
return
|
|
||||||
pos = self.cursorPosition()
|
|
||||||
chars = "0123456789%"
|
|
||||||
chars += DECIMAL_POINT
|
|
||||||
|
|
||||||
s = "".join([i for i in text if i in chars])
|
|
||||||
|
|
||||||
if "%" in s:
|
|
||||||
self.is_perc = True
|
|
||||||
s = s.replace("%", "")
|
|
||||||
else:
|
|
||||||
self.is_perc = False
|
|
||||||
|
|
||||||
if DECIMAL_POINT in s:
|
|
||||||
p = s.find(DECIMAL_POINT)
|
|
||||||
s = s.replace(DECIMAL_POINT, "")
|
|
||||||
s = s[:p] + DECIMAL_POINT + s[p : p + 8]
|
|
||||||
if self.is_perc:
|
|
||||||
s += "%"
|
|
||||||
|
|
||||||
self.setText(s)
|
|
||||||
self.setModified(self.hasFocus())
|
|
||||||
self.setCursorPosition(pos)
|
|
||||||
|
|
||||||
def _get_amount_from_text(self, text: str) -> Union[None, Decimal, int]:
|
|
||||||
try:
|
|
||||||
text = text.replace(DECIMAL_POINT, ".")
|
|
||||||
text = text.replace("%", "")
|
|
||||||
return (Decimal)(text)
|
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _get_text_from_amount(self, amount):
|
|
||||||
out = super()._get_text_from_amount(amount)
|
|
||||||
if self.is_perc:
|
|
||||||
out += "%"
|
|
||||||
return out
|
|
||||||
|
|
||||||
def paintEvent(self, event):
|
|
||||||
QLineEdit.paintEvent(self, event)
|
|
||||||
if self.base_unit:
|
|
||||||
panel = QStyleOptionFrame()
|
|
||||||
self.initStyleOption(panel)
|
|
||||||
textRect = self.style().subElementRect(
|
|
||||||
QStyle.SubElement.SE_LineEditContents, panel, self
|
|
||||||
)
|
|
||||||
textRect.adjust(2, 0, -10, 0)
|
|
||||||
painter = QPainter(self)
|
|
||||||
painter.setPen(ColorScheme.GRAY.as_color())
|
|
||||||
if len(self.text()) == 0:
|
|
||||||
painter.drawText(
|
|
||||||
textRect,
|
|
||||||
int(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter),
|
|
||||||
"""Base class for dialog windows in Bitcoin After Life.
|
|
||||||
|
|
||||||
Provides common functionality for all dialog windows including:
|
|
||||||
- Window modal behavior
|
|
||||||
- Standard button layouts (OK, Cancel)
|
|
||||||
- Size policy management
|
|
||||||
- Parent window handling
|
|
||||||
|
|
||||||
Subclasses should implement:
|
|
||||||
- __init__: Initialize dialog components
|
|
||||||
- setup_ui: Create and configure UI elements
|
|
||||||
- connect_signals: Connect signal-slot connections
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
parent (QWidget): Parent window
|
|
||||||
plugin (BalPlugin): Plugin reference
|
|
||||||
title (str): Dialog window title
|
|
||||||
|
|
||||||
Methods:
|
|
||||||
exec_(): Show dialog modally
|
|
||||||
accept(): Handle dialog acceptance
|
|
||||||
reject(): Handle dialog rejection
|
|
||||||
|
|
||||||
Example:
|
|
||||||
dialog = BalDialog(parent, plugin, "My Dialog")
|
|
||||||
if dialog.exec_() == QDialog.Accepted:
|
|
||||||
# Handle acceptance
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.base_unit() + " or perc value",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class BalDialog(WindowModalDialog):
|
|
||||||
def __init__(self, parent, bal_plugin, title=None, icon="icons/bal32x32.png"):
|
|
||||||
self.parent = parent
|
|
||||||
"""Base class for multi-step wizard dialogs.
|
|
||||||
|
|
||||||
Provides infrastructure for:
|
|
||||||
- Multi-page workflows
|
|
||||||
- Navigation between steps
|
|
||||||
- Progress tracking
|
|
||||||
- Validation at each step
|
|
||||||
- Final submission
|
|
||||||
|
|
||||||
Subclasses implement specific wizards:
|
|
||||||
- BalWizardHeirsWidget: Heir configuration
|
|
||||||
- BalWizardWEDownloadWidget: Wallet export download
|
|
||||||
- BalWizardWEWidget: Wallet export configuration
|
|
||||||
- BalWizardLocktimeAndFeeWidget: Locktime and fee setup
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
current_page (int): Current step index
|
|
||||||
total_pages (int): Total number of steps
|
|
||||||
data (dict): Collected data across steps
|
|
||||||
|
|
||||||
Methods:
|
|
||||||
next_page(): Move to next step
|
|
||||||
prev_page(): Move to previous step
|
|
||||||
validate_current(): Validate current step
|
|
||||||
finish(): Complete the wizard
|
|
||||||
"""
|
|
||||||
|
|
||||||
WindowModalDialog.__init__(self, parent, title)
|
|
||||||
# WindowModalDialog.__init__(self,parent)
|
|
||||||
self.setWindowIcon(read_QIcon_from_bytes(bal_plugin.read_file(icon)))
|
|
||||||
|
|
||||||
|
|
||||||
class BalWizardDialog(BalDialog):
|
class BalWizardDialog(BalDialog):
|
||||||
def __init__(self, bal_window: "BalWindow"):
|
def __init__(self, bal_window: "BalWindow"):
|
||||||
assert bal_window
|
assert bal_window
|
||||||
@@ -1779,17 +1388,6 @@ class BalWizardDialog(BalDialog):
|
|||||||
self.bal_window.update_all()
|
self.bal_window.update_all()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
"""BalWizardWidget class for Bitcoin After Life.
|
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
See class implementation for attributes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
instance = BalWizardWidget(required parameters)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
|
|
||||||
self.bal_window.heir_list_widget.update_will_settings()
|
self.bal_window.heir_list_widget.update_will_settings()
|
||||||
@@ -1855,17 +1453,6 @@ class BalWizardWidget(QWidget):
|
|||||||
def _on_previous(self):
|
def _on_previous(self):
|
||||||
self.on_previous()
|
self.on_previous()
|
||||||
|
|
||||||
"""BalWizardHeirsWidget class for Bitcoin After Life.
|
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
See class implementation for attributes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
instance = BalWizardHeirsWidget(required parameters)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def get_content(self):
|
def get_content(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -1900,17 +1487,6 @@ class BalWizardHeirsWidget(BalWizardWidget):
|
|||||||
def export_to_file(self):
|
def export_to_file(self):
|
||||||
self.bal_window.export_heirs()
|
self.bal_window.export_heirs()
|
||||||
|
|
||||||
"""BalWizardWEDownloadWidget class for Bitcoin After Life.
|
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
See class implementation for attributes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
instance = BalWizardWEDownloadWidget(required parameters)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def add_heir(self):
|
def add_heir(self):
|
||||||
self.bal_window.new_heir_dialog()
|
self.bal_window.new_heir_dialog()
|
||||||
self.heir_list_widget.update()
|
self.heir_list_widget.update()
|
||||||
@@ -1998,17 +1574,6 @@ class BalWizardWEDownloadWidget(BalWizardWidget):
|
|||||||
if self.validate():
|
if self.validate():
|
||||||
return self.on_next()
|
return self.on_next()
|
||||||
|
|
||||||
"""BalWizardWEWidget class for Bitcoin After Life.
|
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
See class implementation for attributes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
instance = BalWizardWEWidget(required parameters)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def import_json_file(self, path):
|
def import_json_file(self, path):
|
||||||
data = read_json_file(path)
|
data = read_json_file(path)
|
||||||
data = self._validate(data)
|
data = self._validate(data)
|
||||||
@@ -2025,17 +1590,6 @@ class BalWizardWEWidget(BalWizardWidget):
|
|||||||
def get_content(self):
|
def get_content(self):
|
||||||
widget = QWidget()
|
widget = QWidget()
|
||||||
vbox = QVBoxLayout(widget)
|
vbox = QVBoxLayout(widget)
|
||||||
"""BalWizardLocktimeAndFeeWidget class for Bitcoin After Life.
|
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
See class implementation for attributes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
instance = BalWizardLocktimeAndFeeWidget(required parameters)
|
|
||||||
"""
|
|
||||||
|
|
||||||
vbox.addWidget(
|
vbox.addWidget(
|
||||||
WillExecutorWidget(
|
WillExecutorWidget(
|
||||||
self,
|
self,
|
||||||
@@ -2145,30 +1699,6 @@ class BalWizardLocktimeAndFeeWidget(BalWizardWidget):
|
|||||||
_("Fees(sats/vbyte):"),
|
_("Fees(sats/vbyte):"),
|
||||||
self.heir_tx_fees,
|
self.heir_tx_fees,
|
||||||
("Fee to be used in the transaction"),
|
("Fee to be used in the transaction"),
|
||||||
"""Non-blocking progress dialog for long operations.
|
|
||||||
|
|
||||||
Provides:
|
|
||||||
- Indeterminate progress bar
|
|
||||||
- Status messages
|
|
||||||
- Cancel button for interruption
|
|
||||||
- Automatic cleanup
|
|
||||||
- Thread-safe operation
|
|
||||||
|
|
||||||
Used for operations like:
|
|
||||||
- Blockchain synchronization
|
|
||||||
- Transaction broadcasting
|
|
||||||
- Will construction
|
|
||||||
- Data loading
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
message (str): Current status message
|
|
||||||
can_cancel (bool): Whether operation can be cancelled
|
|
||||||
|
|
||||||
Methods:
|
|
||||||
update_message(): Update status message
|
|
||||||
cancel(): Interrupt the operation
|
|
||||||
"""
|
|
||||||
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -2233,17 +1763,6 @@ class BalWaitingDialog(BalDialog):
|
|||||||
self.thread.stop()
|
self.thread.stop()
|
||||||
|
|
||||||
def update_message(self, msg):
|
def update_message(self, msg):
|
||||||
"""BalBlockingWaitingDialog class for Bitcoin After Life.
|
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
See class implementation for attributes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
instance = BalBlockingWaitingDialog(required parameters)
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.message_label.setText(msg)
|
self.message_label.setText(msg)
|
||||||
|
|
||||||
def update(self, msg):
|
def update(self, msg):
|
||||||
@@ -2263,17 +1782,6 @@ class BalBlockingWaitingDialog(BalDialog):
|
|||||||
vbox = QVBoxLayout(self)
|
vbox = QVBoxLayout(self)
|
||||||
vbox.addWidget(self.message_label)
|
vbox.addWidget(self.message_label)
|
||||||
self.finished.connect(self.deleteLater) # see #3956
|
self.finished.connect(self.deleteLater) # see #3956
|
||||||
"""bal_checkbox class for Bitcoin After Life.
|
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
See class implementation for attributes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
instance = bal_checkbox(required parameters)
|
|
||||||
"""
|
|
||||||
|
|
||||||
# show popup
|
# show popup
|
||||||
self.show()
|
self.show()
|
||||||
# refresh GUI; needed for popup to appear and for message_label to get drawn
|
# refresh GUI; needed for popup to appear and for message_label to get drawn
|
||||||
@@ -2309,6 +1817,8 @@ class BalBuildWillDialog(BalDialog):
|
|||||||
COLOR_OK = "#05ad05"
|
COLOR_OK = "#05ad05"
|
||||||
|
|
||||||
def __init__(self, bal_window, parent=None):
|
def __init__(self, bal_window, parent=None):
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"""Initialize the Build Will dialog.
|
"""Initialize the Build Will dialog.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -2321,6 +1831,7 @@ class BalBuildWillDialog(BalDialog):
|
|||||||
- Layout management
|
- Layout management
|
||||||
- Network connection
|
- Network connection
|
||||||
"""
|
"""
|
||||||
|
>>>>>>> origin/doc
|
||||||
if not parent:
|
if not parent:
|
||||||
parent = bal_window.window
|
parent = bal_window.window
|
||||||
BalDialog.__init__(self, parent, bal_window.bal_plugin, _("Building Will"))
|
BalDialog.__init__(self, parent, bal_window.bal_plugin, _("Building Will"))
|
||||||
@@ -2328,6 +1839,18 @@ class BalBuildWillDialog(BalDialog):
|
|||||||
self.updatemessage.connect(self.msg_update)
|
self.updatemessage.connect(self.msg_update)
|
||||||
self.bal_window = bal_window
|
self.bal_window = bal_window
|
||||||
self.bal_plugin = bal_window.bal_plugin
|
self.bal_plugin = bal_window.bal_plugin
|
||||||
|
<<<<<<< HEAD
|
||||||
|
self.message_label = QLabel(_("Building Will:"))
|
||||||
|
self.vbox = QVBoxLayout(self)
|
||||||
|
self.vbox.addWidget(self.message_label,0)
|
||||||
|
self.qwidget = QWidget(self)
|
||||||
|
self.vbox.addWidget(self.qwidget,1)
|
||||||
|
self.labelsbox=QVBoxLayout(self.qwidget)
|
||||||
|
self.setMinimumWidth(600)
|
||||||
|
self.setMinimumHeight(100)
|
||||||
|
self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred)
|
||||||
|
self.labels = []
|
||||||
|
=======
|
||||||
|
|
||||||
# Main message label
|
# Main message label
|
||||||
self.message_label = QLabel(_("Building Will:"))
|
self.message_label = QLabel(_("Building Will:"))
|
||||||
@@ -2365,6 +1888,7 @@ class BalBuildWillDialog(BalDialog):
|
|||||||
self.network = Network.get_instance()
|
self.network = Network.get_instance()
|
||||||
self._stopping = False
|
self._stopping = False
|
||||||
|
|
||||||
|
>>>>>>> origin/doc
|
||||||
self.check_row = None
|
self.check_row = None
|
||||||
self.inval_row = None
|
self.inval_row = None
|
||||||
self.build_row = None
|
self.build_row = None
|
||||||
@@ -2814,6 +2338,15 @@ class BalBuildWillDialog(BalDialog):
|
|||||||
w.deleteLater()
|
w.deleteLater()
|
||||||
|
|
||||||
def msg_update(self):
|
def msg_update(self):
|
||||||
|
<<<<<<< HEAD
|
||||||
|
self.clear_layout(self.labelsbox)
|
||||||
|
for label in self.labels:
|
||||||
|
label=label.replace("\n","<br>")
|
||||||
|
qlabel=QLabel(label)
|
||||||
|
self.labelsbox.addWidget(QLabel(label),1)
|
||||||
|
self.setMinimumHeight(30*(len(self.labels)+2))
|
||||||
|
|
||||||
|
=======
|
||||||
"""Updates the UI with new messages using a debounced queue system.
|
"""Updates the UI with new messages using a debounced queue system.
|
||||||
|
|
||||||
This method implements the following logic:
|
This method implements the following logic:
|
||||||
@@ -2874,36 +2407,6 @@ class BalBuildWillDialog(BalDialog):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Log errors without interrupting processing
|
# Log errors without interrupting processing
|
||||||
"""Table widget for managing heir configurations.
|
|
||||||
|
|
||||||
Provides a tabular interface for:
|
|
||||||
- Adding, editing, and removing heirs
|
|
||||||
- Configuring inheritance percentages
|
|
||||||
- Setting heir addresses and conditions
|
|
||||||
- Validating heir configurations
|
|
||||||
- Sorting and filtering heir list
|
|
||||||
|
|
||||||
Inherits from MyTreeView for:
|
|
||||||
- Column-based data display
|
|
||||||
- Sorting functionality
|
|
||||||
- Filtering capabilities
|
|
||||||
- Model-view architecture
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
bal_window (BalWindow): Reference to main window
|
|
||||||
main_window (QMainWindow): Parent window
|
|
||||||
model (QStandardItemModel): Data model for heirs
|
|
||||||
|
|
||||||
Columns:
|
|
||||||
NAME: Heir name
|
|
||||||
ADDRESS: Bitcoin address
|
|
||||||
AMOUNT: Inheritance percentage
|
|
||||||
|
|
||||||
Example:
|
|
||||||
widget = HeirListWidget(window, parent)
|
|
||||||
widget.update() # Refresh heir list
|
|
||||||
"""
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
logging.error(f"Error creating label in BalBuildWillDialog: {e}")
|
logging.error(f"Error creating label in BalBuildWillDialog: {e}")
|
||||||
|
|
||||||
@@ -2911,6 +2414,7 @@ class BalBuildWillDialog(BalDialog):
|
|||||||
self._message_queue = []
|
self._message_queue = []
|
||||||
self.setMinimumHeight(min(30 * (len(self.labels) + 2), 400)) # Max height limit
|
self.setMinimumHeight(min(30 * (len(self.labels) + 2), 400)) # Max height limit
|
||||||
|
|
||||||
|
>>>>>>> origin/doc
|
||||||
|
|
||||||
def get_text(self):
|
def get_text(self):
|
||||||
return self.message_label.text()
|
return self.message_label.text()
|
||||||
@@ -3183,34 +2687,6 @@ class HeirListWidget(MyTreeView, MessageBoxMixin):
|
|||||||
|
|
||||||
return toolbar
|
return toolbar
|
||||||
|
|
||||||
"""Widget for previewing Will documents before signing.
|
|
||||||
|
|
||||||
Provides functionality to:
|
|
||||||
- Render Will in human-readable format
|
|
||||||
- Highlight important clauses and conditions
|
|
||||||
- Show inheritance distribution
|
|
||||||
- Validate Will structure
|
|
||||||
- Generate PDF preview
|
|
||||||
|
|
||||||
Uses MyTreeView for:
|
|
||||||
- Column-based preview display
|
|
||||||
- Sorting and filtering
|
|
||||||
- Efficient rendering of large documents
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
bal_window (BalWindow): Reference to main window
|
|
||||||
main_window (QMainWindow): Parent window
|
|
||||||
|
|
||||||
Methods:
|
|
||||||
update(): Refresh preview display
|
|
||||||
validate(): Check Will structure
|
|
||||||
export_pdf(): Generate PDF document
|
|
||||||
|
|
||||||
Example:
|
|
||||||
preview = PreviewList(window, parent)
|
|
||||||
preview.update()
|
|
||||||
"""
|
|
||||||
|
|
||||||
def update_will_settings(self):
|
def update_will_settings(self):
|
||||||
try:
|
try:
|
||||||
self.heir_locktime.set_locktime(self.bal_window.will_settings["locktime"])
|
self.heir_locktime.set_locktime(self.bal_window.will_settings["locktime"])
|
||||||
@@ -3488,17 +2964,6 @@ class PreviewList(MyTreeView):
|
|||||||
close_window.build_will_task()
|
close_window.build_will_task()
|
||||||
|
|
||||||
will = {}
|
will = {}
|
||||||
"""PreviewDialog class for Bitcoin After Life.
|
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
See class implementation for attributes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
instance = PreviewDialog(required parameters)
|
|
||||||
"""
|
|
||||||
|
|
||||||
for wid, w in self.bal_window.willitems.items():
|
for wid, w in self.bal_window.willitems.items():
|
||||||
if (
|
if (
|
||||||
w.get_status("VALID")
|
w.get_status("VALID")
|
||||||
@@ -3580,17 +3045,6 @@ class PreviewDialog(BalDialog, MessageBoxMixin):
|
|||||||
def update(self):
|
def update(self):
|
||||||
self.transactions_list.update()
|
self.transactions_list.update()
|
||||||
|
|
||||||
"""WillDetailDialog class for Bitcoin After Life.
|
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
See class implementation for attributes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
instance = WillDetailDialog(required parameters)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def is_hidden(self):
|
def is_hidden(self):
|
||||||
return self.isMinimized() or self.isHidden()
|
return self.isMinimized() or self.isHidden()
|
||||||
|
|
||||||
@@ -3691,17 +3145,6 @@ class WillDetailDialog(BalDialog):
|
|||||||
toggle = _("Unhide")
|
toggle = _("Unhide")
|
||||||
self.toggle_replace_button.setText(f"{toggle} {_('replaced')}")
|
self.toggle_replace_button.setText(f"{toggle} {_('replaced')}")
|
||||||
self.update()
|
self.update()
|
||||||
"""WillWidget class for Bitcoin After Life.
|
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
See class implementation for attributes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
instance = WillWidget(required parameters)
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def toggle_invalidated(self):
|
def toggle_invalidated(self):
|
||||||
self.bal_window.bal_plugin.hide_invalidated()
|
self.bal_window.bal_plugin.hide_invalidated()
|
||||||
@@ -3793,17 +3236,6 @@ class WillWidget(QWidget):
|
|||||||
decoded_amount = Util.decode_amount(
|
decoded_amount = Util.decode_amount(
|
||||||
self.will[w].we["base_fee"], self.parent.decimal_point
|
self.will[w].we["base_fee"], self.parent.decimal_point
|
||||||
)
|
)
|
||||||
"""WillExecutorListWidget class for Bitcoin After Life.
|
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
See class implementation for attributes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
instance = WillExecutorListWidget(required parameters)
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
detaillayout.addWidget(
|
detaillayout.addWidget(
|
||||||
qlabel(
|
qlabel(
|
||||||
@@ -4035,31 +3467,6 @@ class WillExecutorListWidget(MyTreeView):
|
|||||||
items[self.Columns.BASE_FEE].setData(
|
items[self.Columns.BASE_FEE].setData(
|
||||||
url, self.ROLE_HEIR_KEY + self.Columns.BASE_FEE
|
url, self.ROLE_HEIR_KEY + self.Columns.BASE_FEE
|
||||||
)
|
)
|
||||||
"""Widget for executing Will transactions.
|
|
||||||
|
|
||||||
Handles:
|
|
||||||
- Transaction construction
|
|
||||||
- Fee calculation
|
|
||||||
- Signature collection
|
|
||||||
- Transaction broadcasting
|
|
||||||
- Status monitoring
|
|
||||||
|
|
||||||
Coordinates with:
|
|
||||||
- WillExecutorListWidget: List of executors
|
|
||||||
- WillExecutorDialog: Detailed executor configuration
|
|
||||||
- BalWindow: Main application window
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
will (Will): Will being executed
|
|
||||||
executors (list): List of executor configurations
|
|
||||||
network (Network): Network interface
|
|
||||||
|
|
||||||
Methods:
|
|
||||||
execute(): Start transaction execution
|
|
||||||
stop(): Interrupt execution
|
|
||||||
validate(): Check transaction validity
|
|
||||||
"""
|
|
||||||
|
|
||||||
items[self.Columns.INFO].setData(
|
items[self.Columns.INFO].setData(
|
||||||
url, self.ROLE_HEIR_KEY + self.Columns.INFO
|
url, self.ROLE_HEIR_KEY + self.Columns.INFO
|
||||||
)
|
)
|
||||||
@@ -4164,17 +3571,6 @@ class WillExecutorWidget(QWidget, MessageBoxMixin):
|
|||||||
self.willexecutors_list.update,
|
self.willexecutors_list.update,
|
||||||
)
|
)
|
||||||
|
|
||||||
"""WillExecutorDialog class for Bitcoin After Life.
|
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
See class implementation for attributes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
instance = WillExecutorDialog(required parameters)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def update_willexecutors(self, wes=None):
|
def update_willexecutors(self, wes=None):
|
||||||
if not wes:
|
if not wes:
|
||||||
wes = self.willexecutors_list
|
wes = self.willexecutors_list
|
||||||
@@ -4210,17 +3606,6 @@ class WillExecutorDialog(BalDialog, MessageBoxMixin):
|
|||||||
self.setMinimumSize(1000, 200)
|
self.setMinimumSize(1000, 200)
|
||||||
|
|
||||||
vbox = QVBoxLayout(self)
|
vbox = QVBoxLayout(self)
|
||||||
"""CheckAliveException class for Bitcoin After Life.
|
|
||||||
|
|
||||||
This class provides functionality for managing various Bitcoin After Life features.
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
See class implementation for attributes
|
|
||||||
|
|
||||||
Example:
|
|
||||||
instance = CheckAliveException(required parameters)
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.will_executor_list_widget = WillExecutorWidget(
|
self.will_executor_list_widget = WillExecutorWidget(
|
||||||
self, self.bal_window, self.willexecutors_list
|
self, self.bal_window, self.willexecutors_list
|
||||||
)
|
)
|
||||||
@@ -4247,6 +3632,8 @@ class CheckAliveException(Exception):
|
|||||||
def __init__(self,timestamp_to_check):
|
def __init__(self,timestamp_to_check):
|
||||||
self.timestamp_to_check = timestamp_to_check
|
self.timestamp_to_check = timestamp_to_check
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
"""Explicit cleanup to prevent memory leaks.
|
"""Explicit cleanup to prevent memory leaks.
|
||||||
@@ -4263,4 +3650,5 @@ class CheckAliveException(Exception):
|
|||||||
self._message_timer.deleteLater()
|
self._message_timer.deleteLater()
|
||||||
self.clear_layout(self.labelsbox)
|
self.clear_layout(self.labelsbox)
|
||||||
|
|
||||||
|
>>>>>>> origin/doc
|
||||||
return "Check alive expired please update it: {}".format(datetime.fromtimestamp(self.timestamp_to_check).isoformat())
|
return "Check alive expired please update it: {}".format(datetime.fromtimestamp(self.timestamp_to_check).isoformat())
|
||||||
|
|||||||
Reference in New Issue
Block a user