Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GUI improvements and bugfixes #12

Merged
merged 1 commit into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ repos:
- types-toml


- repo: local
hooks:
- id: update-poetry-version
name: Update Poetry Version
entry: python .update_version.py
language: python
always_run: true
files: pyproject.toml
additional_dependencies:
- toml

# - repo: https://github.com/PyCQA/bandit
# rev: 1.7.6 # Use the latest version
Expand Down
50 changes: 50 additions & 0 deletions .update_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#
# Bitcoin Safe
# Copyright (C) 2024 Andreas Griffin
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of version 3 of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see https://www.gnu.org/licenses/gpl-3.0.html
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

import toml

from bitcoin_safe import __version__


def update_poetry_version(file_path, new_version):
# Read the pyproject.toml file
with open(file_path, "r") as file:
data = toml.load(file)

# Update the version under tool.poetry
if "tool" in data and "poetry" in data["tool"] and "version" in data["tool"]["poetry"]:
data["tool"]["poetry"]["version"] = new_version
# Write the updated data back to pyproject.toml
with open(file_path, "w") as file:
toml.dump(data, file)
print(f"Version updated to {new_version} in pyproject.toml")
else:
print("Could not find the 'tool.poetry.version' key in the pyproject.toml")


update_poetry_version("pyproject.toml", __version__)
3 changes: 2 additions & 1 deletion bitcoin_safe/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
__version__ = "0.7.1a0"
# this is the source of the version information
__version__ = "0.7.2a0"
141 changes: 83 additions & 58 deletions bitcoin_safe/gui/qt/address_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,34 +28,79 @@


import logging
import typing

from bitcoin_qr_tools.qr_widgets import QRCodeWidgetSVG

from bitcoin_safe.config import UserConfig
from bitcoin_safe.gui.qt.buttonedit import ButtonEdit
from bitcoin_safe.gui.qt.recipients import RecipientTabWidget
from bitcoin_safe.mempool import MempoolData
from bitcoin_safe.util import serialized_to_hex

logger = logging.getLogger(__name__)

import bdkpython as bdk
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QKeyEvent
from PyQt6.QtWidgets import (
QFormLayout,
QHBoxLayout,
QLabel,
QSizePolicy,
QTabWidget,
QTextEdit,
QVBoxLayout,
QWidget,
)

from ...signals import Signals
from ...wallet import Wallet
from .hist_list import HistList, HistListWithToolbar
from .hist_list import HistList
from .util import Buttons, CloseButton


class AddressDetailsAdvanced(QWidget):
def __init__(
self, bdk_address: bdk.Address, address_path_str: str, parent: typing.Optional["QWidget"]
) -> None:
super().__init__(parent)

form_layout = QFormLayout(self)
form_layout.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)

try:
script_pubkey = serialized_to_hex(bdk_address.script_pubkey().to_bytes())
except BaseException:
script_pubkey = None
if script_pubkey:
pubkey_e = ButtonEdit(script_pubkey)
pubkey_e.button_container.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed)
pubkey_e.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed)

pubkey_e.add_copy_button()
pubkey_e.setReadOnly(True)

form_layout.addRow(self.tr("Script Pubkey"), pubkey_e)

if address_path_str:
der_path_e = ButtonEdit(address_path_str, input_field=QTextEdit())
der_path_e.add_copy_button()
der_path_e.setFixedHeight(50)
der_path_e.setReadOnly(True)

form_layout.addRow(self.tr("Address descriptor"), der_path_e)


class QRAddress(QRCodeWidgetSVG):
def __init__(
self,
) -> None:
super().__init__(clickable=False)
self.setMaximumSize(150, 150)

def set_address(self, bdk_address: bdk.Address):
self.set_data_list([bdk_address.to_qr_uri()])


class AddressDialog(QWidget):
def __init__(
self,
Expand Down Expand Up @@ -83,63 +128,37 @@ def __init__(
self.setLayout(vbox)

upper_widget = QWidget()
upper_widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
upper_widget_layout = QHBoxLayout(upper_widget)
upper_widget_layout.setContentsMargins(0, 0, 0, 0)
# upper_widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
upper_widget.setLayout(QHBoxLayout())
upper_widget.layout().setContentsMargins(0, 0, 0, 0)

vbox.addWidget(upper_widget)

self.tabs = QTabWidget()
upper_widget_layout.addWidget(self.tabs)

self.tab_details = QWidget()
tab1_layout = QVBoxLayout(self.tab_details)
tab1_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
self.tabs.addTab(self.tab_details, "")
self.tab_advanced = QWidget()
tab2_layout = QVBoxLayout(self.tab_advanced)
tab2_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
self.tabs.addTab(self.tab_advanced, "")

address_info_min = self.wallet.get_address_info_min(address)
if address_info_min:

address_title = (
self.tr("Receiving address of wallet '{wallet_id}' (with index {index})")
if address_info_min.keychain == bdk.KeychainKind.EXTERNAL
else self.tr("Change address of wallet '{wallet_id}' (with index {index})")
).format(wallet_id=wallet.id, index=address_info_min.index)
tab1_layout.addWidget(QLabel(self.tr(address_title) + ":"))
self.addr_e = ButtonEdit(self.address)
self.addr_e.setReadOnly(True)
self.addr_e.add_copy_button()
# self.addr_e.setStyleSheet(f"background-color: {ColorScheme.GREEN.as_color(True).name()};")
tab1_layout.addWidget(self.addr_e)
self.recipient_tabs = RecipientTabWidget(
network=wallet.network,
allow_edit=False,
parent=self,
signals=self.signals,
tab_string=self.tr('Address of wallet "{id}"'),
dismiss_label_on_focus_loss=True,
)
self.recipient_tabs.address = self.address
label = wallet.labels.get_label(self.address)
self.recipient_tabs.label = label if label else ""
self.recipient_tabs.amount = wallet.get_addr_balance(self.address).total

try:
script_pubkey = serialized_to_hex(self.bdk_address.script_pubkey().to_bytes())
except BaseException:
script_pubkey = None
if script_pubkey:
tab2_layout.addWidget(QLabel(self.tr("Script Pubkey") + ":"))
pubkey_e = ButtonEdit(script_pubkey)
pubkey_e.add_copy_button()
pubkey_e.setReadOnly(True)
tab2_layout.addWidget(pubkey_e)
upper_widget.layout().addWidget(self.recipient_tabs)

address_path_str = self.wallet.get_address_path_str(address)
if address_path_str:
tab2_layout.addWidget(QLabel(self.tr("Address descriptor") + ":"))
der_path_e = ButtonEdit(address_path_str, input_field=QTextEdit())
der_path_e.add_copy_button()
der_path_e.setFixedHeight(50)
der_path_e.setReadOnly(True)
tab2_layout.addWidget(der_path_e)
self.tab_advanced = AddressDetailsAdvanced(
bdk_address=self.bdk_address,
address_path_str=self.wallet.get_address_path_str(address),
parent=self,
)
self.recipient_tabs.addTab(self.tab_advanced, "")

self.qr_code = QRCodeWidgetSVG()
self.qr_code.set_data_list([self.bdk_address.to_qr_uri()])
self.qr_code.setMaximumWidth(150)
upper_widget_layout.addWidget(self.qr_code)
self.qr_code = QRAddress()
self.qr_code.set_address(self.bdk_address)
upper_widget.layout().addWidget(self.qr_code)

self.hist_list = HistList(
self.fx,
Expand All @@ -154,12 +173,18 @@ def __init__(
address_domain=[self.address],
column_widths={HistList.Columns.TXID: 100},
)
toolbar = HistListWithToolbar(self.hist_list, self.config, parent=self)
vbox.addWidget(toolbar)
vbox.addWidget(self.hist_list)

vbox.addLayout(Buttons(CloseButton(self)))
self.setupUi()

# Override keyPressEvent method
def keyPressEvent(self, event: QKeyEvent) -> None:
# Check if the pressed key is 'Esc'
if event.key() == Qt.Key.Key_Escape:
# Close the widget
self.close()

def setupUi(self) -> None:
self.tabs.setTabText(self.tabs.indexOf(self.tab_details), self.tr("Details"))
self.tabs.setTabText(self.tabs.indexOf(self.tab_advanced), self.tr("Advanced"))
self.recipient_tabs.updateUi()
self.recipient_tabs.setTabText(self.recipient_tabs.indexOf(self.tab_advanced), self.tr("Advanced"))
Loading
Loading