1
.gitignore
vendored
@ -1,6 +1,7 @@
|
||||
.DS_Store
|
||||
home.admin/.DS_Store
|
||||
*.log
|
||||
*.pyc
|
||||
__pycache__
|
||||
rpc_pb2.pyc
|
||||
rpc_pb2_grpc.pyc
|
||||
|
@ -599,6 +599,10 @@ echo "to switch between python2/3: sudo update-alternatives --config python"
|
||||
sudo apt-get -f -y install virtualenv
|
||||
sudo chown -R admin /home/admin
|
||||
sudo -u admin bash -c "cd; virtualenv python-env-lnd; source /home/admin/python-env-lnd/bin/activate; pip install grpcio grpcio-tools googleapis-common-protos pathlib2"
|
||||
|
||||
# This Python3 virtualenv includes the site-packages because access to the PyQt5
|
||||
# libs - which are installed system-wide (via apt-get) - is needed for TouchUI.
|
||||
sudo -u admin bash -c "cd; virtualenv -p python3 --system-site-packages python3-env-lnd"
|
||||
echo ""
|
||||
|
||||
echo ""
|
||||
|
@ -1,161 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# 00infoLCDTK.py
|
||||
#
|
||||
# called by #
|
||||
# /home/pi/autostart.sh
|
||||
# dev/test/run with:
|
||||
# sudo -i -u pi DISPLAY=:0.0 /usr/bin/python3 /home/admin/00infoLCDTK.py
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import logging
|
||||
import logging.config
|
||||
import tkinter as tk
|
||||
|
||||
COLOR = "black"
|
||||
WINFO = None
|
||||
|
||||
log = logging.getLogger()
|
||||
|
||||
|
||||
def setup_logging(default_path='00infoLCDw.json'):
|
||||
"""Setup logging configuration"""
|
||||
path = default_path
|
||||
if os.path.exists(path):
|
||||
with open(path, 'rt') as f:
|
||||
config = json.load(f)
|
||||
logging.config.dictConfig(config)
|
||||
else: # if $default_path does not exist use the following default log setup
|
||||
default_config_as_json = """
|
||||
{
|
||||
"version": 1,
|
||||
"disable_existing_loggers": false,
|
||||
"formatters": {
|
||||
"simple": {
|
||||
"format": "%(asctime)s - %(levelname)s - %(message)s"
|
||||
},
|
||||
"extended": {
|
||||
"format": "%(asctime)s - %(name)s - %(levelname)s - %(module)s:%(lineno)d - %(message)s"
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
"handlers": {
|
||||
"console": {
|
||||
"class": "logging.StreamHandler",
|
||||
"level": "INFO",
|
||||
"formatter": "simple",
|
||||
"stream": "ext://sys.stdout"
|
||||
},
|
||||
|
||||
"file_handler": {
|
||||
"class": "logging.handlers.RotatingFileHandler",
|
||||
"level": "DEBUG",
|
||||
"formatter": "extended",
|
||||
"filename": "00infoLCDTK.log",
|
||||
"maxBytes": 10485760,
|
||||
"backupCount": 0,
|
||||
"encoding": "utf8"
|
||||
}
|
||||
},
|
||||
|
||||
"loggers": {
|
||||
"infoblitz": {
|
||||
"level": "INFO",
|
||||
"handlers": ["console", "file_handler"],
|
||||
"propagate": "no"
|
||||
}
|
||||
},
|
||||
|
||||
"root": {
|
||||
"level": "INFO",
|
||||
"handlers": ["console", "file_handler"]
|
||||
}
|
||||
}
|
||||
"""
|
||||
config = json.loads(default_config_as_json)
|
||||
logging.config.dictConfig(config)
|
||||
|
||||
|
||||
def callback_b1():
|
||||
global WINFO
|
||||
log.info("clicked b1 - no action yet (placeholder)")
|
||||
#if sys.platform != "win32":
|
||||
# os.system("xterm -fn fixed -into %d +sb -hold /home/admin/00infoLCD.sh &" % WINFO)
|
||||
|
||||
|
||||
def callback_b2():
|
||||
global WINFO
|
||||
log.info("clicked b2 - no action yet (placeholder)")
|
||||
#if sys.platform != "win32":
|
||||
# os.system("xterm -fn fixed -into %d +sb -hold /home/admin/XXbutton2.sh &" % WINFO)
|
||||
|
||||
def callback_b3():
|
||||
global WINFO
|
||||
log.info("clicked b3 - no action yet")
|
||||
#if sys.platform != "win32":
|
||||
# os.system("xterm -fn fixed -into %d +sb -hold /home/admin/XXbutton3.sh &" % WINFO)
|
||||
|
||||
def callback_b4():
|
||||
global WINFO
|
||||
log.info("clicked b4")
|
||||
if sys.platform != "win32":
|
||||
os.system("xterm -fn fixed -into %d +sb -hold /home/admin/XXshutdown.sh &" % WINFO)
|
||||
|
||||
|
||||
def main():
|
||||
global WINFO
|
||||
setup_logging()
|
||||
log.info("Starting 00infoLCDTK.py")
|
||||
|
||||
# LCD root
|
||||
root = tk.Tk()
|
||||
root.config(bg=COLOR)
|
||||
root.overrideredirect(1)
|
||||
root.geometry("480x320+0+0")
|
||||
root.title("RaspiBlitz")
|
||||
|
||||
# but LCD on canvas
|
||||
entry = tk.Entry(root)
|
||||
entry.config(bg=COLOR, highlightbackground=COLOR)
|
||||
entry.pack(side="bottom", fill="x")
|
||||
|
||||
# button frame
|
||||
frame1 = tk.Frame(entry, width=80, background="black")
|
||||
frame1.pack(side="left", fill="both", expand=True)
|
||||
|
||||
# button 1 - no action yet (placeholder)
|
||||
button1 = tk.Button(frame1, text='\u002d', fg='black', command=callback_b1, height = 1, width = 1)
|
||||
button1.pack(pady=24)
|
||||
|
||||
# button 2 - no action yet (placeholder)
|
||||
button2 = tk.Button(frame1, text='\u002d', fg='black', command=callback_b2, height = 1, width = 1)
|
||||
button2.pack(pady=24)
|
||||
|
||||
# button 3 - no action yet (placeholder)
|
||||
button3 = tk.Button(frame1, text='\u002d', fg='black', command=callback_b3, height = 1, width = 1)
|
||||
button3.pack(pady=24)
|
||||
#label3 = tk.Label(frame1, text='1.3', bg=COLOR, fg='white')
|
||||
#label3.pack(pady=24)
|
||||
|
||||
# button 4 - no action yet (power down)
|
||||
button4 = tk.Button(frame1, text='\N{BLACK CIRCLE}', fg='red', command=callback_b4, height = 1, width = 1)
|
||||
button4.pack(pady=24)
|
||||
|
||||
# content frame
|
||||
frame2 = tk.Frame(entry, width=400, background="grey")
|
||||
frame2.pack(side="right", fill="both", expand=True)
|
||||
|
||||
# run terminal in
|
||||
WINFO = frame2.winfo_id()
|
||||
if sys.platform != "win32":
|
||||
os.system("xterm -fn fixed -into %d +sb -hold /home/admin/00infoLCD.sh &" % WINFO)
|
||||
|
||||
# run
|
||||
root.mainloop()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
3
home.admin/BlitzTUI/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
BlitzTUI.egg-info/*
|
||||
build/*
|
||||
dist/*
|
30
home.admin/BlitzTUI/CHANGELOG.md
Normal file
@ -0,0 +1,30 @@
|
||||
# Changelog
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.41.0] - 2019-11-15
|
||||
### Added
|
||||
- reduce default channel check interval to 40
|
||||
- increase invoice monitor time to 1 hour
|
||||
|
||||
## [0.39.0] - 2019-11-04
|
||||
### Added
|
||||
- fix logging
|
||||
- update blitz.touchscreen.sh scripts
|
||||
|
||||
## [0.36.0] - 2019-11-03
|
||||
### Added
|
||||
- require at least gRPC (grpcio) version 1.24.3 (to address atomic_exchange_8 issue)
|
||||
- fix issue on "not-default" setup (not bitcoin/mainnet)
|
||||
|
||||
## [0.29.0] - 2019-11-02
|
||||
### Added
|
||||
- almost all must-have features have been implemented
|
||||
|
||||
|
||||
## [0.22.2] - 2019-10-27
|
||||
### Added
|
||||
- initial creation
|
21
home.admin/BlitzTUI/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018-2019 The RaspiBlitz developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
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.
|
1
home.admin/BlitzTUI/MANIFEST.in
Normal file
@ -0,0 +1 @@
|
||||
include CHANGELOG.md
|
27
home.admin/BlitzTUI/Makefile
Normal file
@ -0,0 +1,27 @@
|
||||
# Makefile
|
||||
|
||||
build:
|
||||
python setup.py sdist bdist_wheel
|
||||
|
||||
build-ui:
|
||||
pyuic5 -x --import-from "." -o blitztui/ui/qcode.py designer/qcode.ui
|
||||
pyuic5 -x --import-from "." -o blitztui/ui/home.py designer/home.ui
|
||||
pyuic5 -x --import-from "." -o blitztui/ui/off.py designer/off.ui
|
||||
pyuic5 -x --import-from "." -o blitztui/ui/invoice.py designer/invoice.ui
|
||||
pyrcc5 -o blitztui/ui/resources_rc.py resources.qrc
|
||||
|
||||
clean:
|
||||
rm -rf .eggs .tox .coverage .coverage.data .cache build
|
||||
rm -rf blitz-tui.log BlitzTUI.egg-info
|
||||
find ./ -iname "*.pyc" -delete
|
||||
find ./ -type d -iname "__pycache__" -delete
|
||||
|
||||
test:
|
||||
tox
|
||||
|
||||
upload:
|
||||
twine upload --skip-existing dist/* -r pypi
|
||||
|
||||
upload-test:
|
||||
twine upload --skip-existing dist/* -r pypitest
|
||||
|
65
home.admin/BlitzTUI/README.md
Normal file
@ -0,0 +1,65 @@
|
||||
# BlitzTUI
|
||||
|
||||
[![VersionBadge](https://badge.fury.io/py/BlitzTUI.svg)](https://badge.fury.io/)
|
||||
[![LicenseBadge](https://img.shields.io/badge/license-MIT-blue.svg)](https://shields.io/)
|
||||
[![PythonVersions](https://img.shields.io/badge/python-3.4%2C%203.5%2C%203.6%2C%203.7%2C%203.8-blue.svg)](https://shields.io/)
|
||||
|
||||
BlitzTUI is a part of the RaspiBlitz project and implements a Touch User Interface in PyQt5.
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
### Prerequisite
|
||||
|
||||
QT is needed. Please install PyQt5 (see below).
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
#### Debian/Ubuntu (and similar)
|
||||
|
||||
```
|
||||
apt-get install python3-pyqt5
|
||||
```
|
||||
|
||||
#### PIP
|
||||
|
||||
The PIP dependencies are installed automatically - this listing is "FYI"
|
||||
|
||||
* grpcio
|
||||
* googleapis-common-protos
|
||||
* inotify
|
||||
* psutil
|
||||
* pyqtspinner
|
||||
* qrcode
|
||||
|
||||
|
||||
### Install BlitzTUI
|
||||
|
||||
```
|
||||
pip install BlitzTUI
|
||||
```
|
||||
|
||||
**or** consider using a virtual environment
|
||||
|
||||
```
|
||||
virtualenv -p python3 --system-site-packages venv
|
||||
source venv/bin/activate
|
||||
pip install BlitzTUI
|
||||
```
|
||||
|
||||
|
||||
## Error Messages
|
||||
|
||||
For now the following warning/error/info messages can be ignored. If anybody knows how to suppress
|
||||
or fix them please send a PR (or open an issue).
|
||||
|
||||
```
|
||||
libEGL warning: DRI2: failed to authenticate
|
||||
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-pi'
|
||||
2019-11-02 20:01:21,504 - root - INFO - main:214 - /usr/bin/xterm: cannot load font "-Misc-Fixed-medium-R-*-*-13-120-75-75-C-120-ISO10646-1"
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](http://en.wikipedia.org/wiki/MIT_License)
|
9
home.admin/BlitzTUI/blitztui/__init__.py
Normal file
@ -0,0 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
from blitztui.version import __version__
|
||||
from blitztui.file_logger import setup_logging
|
||||
|
||||
log = logging.getLogger()
|
||||
setup_logging()
|
||||
log.info("Starting BlitzTUI v{}".format(__version__))
|
273
home.admin/BlitzTUI/blitztui/client.py
Normal file
@ -0,0 +1,273 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import base64
|
||||
import codecs
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from os.path import isfile
|
||||
|
||||
import grpc
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
IS_WIN32_ENV = sys.platform == "win32"
|
||||
|
||||
if IS_WIN32_ENV:
|
||||
cur_path = os.path.abspath(os.path.curdir)
|
||||
config_script1 = os.path.join(cur_path, "home.admin", "config.scripts")
|
||||
config_script2 = os.path.abspath(os.path.join(cur_path, "..", "..", "home.admin", "config.scripts"))
|
||||
sys.path.insert(1, config_script1)
|
||||
sys.path.insert(1, config_script2)
|
||||
else:
|
||||
sys.path.insert(1, '/home/admin/config.scripts')
|
||||
|
||||
from lndlibs import rpc_pb2 as ln
|
||||
try:
|
||||
from lndlibs import rpc_pb2_grpc as lnrpc
|
||||
except ModuleNotFoundError as err:
|
||||
log.error("ModuleNotFoundError - most likely an issue with incompatible Python3 import.\n"
|
||||
"Please run the following two lines to fix this: \n"
|
||||
"\n"
|
||||
"sed -i -E '1 a from __future__ import absolute_import' "
|
||||
"/home/admin/config.scripts/lndlibs/rpc_pb2_grpc.py\n"
|
||||
"sed -i -E 's/^(import.*_pb2)/from . \\1/' /home/admin/config.scripts/lndlibs/rpc_pb2_grpc.py")
|
||||
sys.exit(1)
|
||||
|
||||
if not IS_WIN32_ENV:
|
||||
import psutil
|
||||
|
||||
MACAROON_LIST = ["admin", "readonly", "invoice"]
|
||||
|
||||
|
||||
class AdminStub(lnrpc.LightningStub):
|
||||
def __init__(self, network="bitcoin", chain="main"):
|
||||
self.channel = get_rpc_channel(macaroon_path=build_macaroon_path("admin", network=network, chain=chain))
|
||||
super().__init__(self.channel)
|
||||
|
||||
|
||||
class ReadOnlyStub(lnrpc.LightningStub):
|
||||
def __init__(self, network="bitcoin", chain="main"):
|
||||
self.channel = get_rpc_channel(macaroon_path=build_macaroon_path("readonly", network=network, chain=chain))
|
||||
super().__init__(self.channel)
|
||||
|
||||
|
||||
class InvoiceStub(lnrpc.LightningStub):
|
||||
def __init__(self, network="bitcoin", chain="main"):
|
||||
self.channel = get_rpc_channel(macaroon_path=build_macaroon_path("invoice", network=network, chain=chain))
|
||||
super().__init__(self.channel)
|
||||
|
||||
|
||||
def convert_r_hash(r_hash):
|
||||
""" convert_r_hash
|
||||
|
||||
>>> convert_r_hash("+eMo9YTaZIjkJacclb6LYUocwa0q7cgVOBPf/0aclYQ=")
|
||||
'f9e328f584da6488e425a71c95be8b614a1cc1ad2aedc8153813dfff469c9584'
|
||||
|
||||
"""
|
||||
r_hash_bytes = codecs.decode(r_hash.encode(), 'base64')
|
||||
r_hash_hex_bytes = codecs.encode(r_hash_bytes, 'hex')
|
||||
return r_hash_hex_bytes.decode()
|
||||
|
||||
|
||||
def convert_r_hash_hex(r_hash_hex):
|
||||
""" convert_r_hash_hex
|
||||
|
||||
>>> convert_r_hash_hex("f9e328f584da6488e425a71c95be8b614a1cc1ad2aedc8153813dfff469c9584")
|
||||
'+eMo9YTaZIjkJacclb6LYUocwa0q7cgVOBPf/0aclYQ='
|
||||
|
||||
"""
|
||||
r_hash = codecs.decode(r_hash_hex, 'hex')
|
||||
r_hash_b64_bytes = base64.b64encode(r_hash)
|
||||
return r_hash_b64_bytes.decode()
|
||||
|
||||
|
||||
def convert_r_hash_hex_bytes(r_hash_hex_bytes):
|
||||
""" convert_r_hash_hex_bytes
|
||||
|
||||
>>> convert_r_hash_hex_bytes(b'\xf9\xe3(\xf5\x84\xdad\x88\xe4%\xa7\x1c\x95\xbe\x8baJ\x1c\xc1\xad*\xed\xc8\x158\x13\xdf\xffF\x9c\x95\x84')
|
||||
'f9e328f584da6488e425a71c95be8b614a1cc1ad2aedc8153813dfff469c9584'
|
||||
|
||||
"""
|
||||
r_hash_hex_bytes = codecs.encode(r_hash_hex_bytes, 'hex')
|
||||
return r_hash_hex_bytes.decode()
|
||||
|
||||
|
||||
def get_rpc_channel(host="localhost", port="10009", cert_path=None, macaroon_path=None):
|
||||
if not macaroon_path:
|
||||
raise Exception("need to specify a macaroon path!")
|
||||
|
||||
def metadata_callback(context, callback):
|
||||
# for more info see grpc docs
|
||||
callback([('macaroon', macaroon)], None)
|
||||
|
||||
# Due to updated ECDSA generated tls.cert we need to let gprc know that
|
||||
# we need to use that cipher suite otherwise there will be a handshake
|
||||
# error when we communicate with the lnd rpc server.
|
||||
os.environ["GRPC_SSL_CIPHER_SUITES"] = 'HIGH+ECDSA'
|
||||
|
||||
if not cert_path:
|
||||
cert_path = os.path.expanduser('~/.lnd/tls.cert')
|
||||
|
||||
assert isfile(cert_path) and os.access(cert_path, os.R_OK), \
|
||||
"File {} doesn't exist or isn't readable".format(cert_path)
|
||||
cert = open(cert_path, 'rb').read()
|
||||
|
||||
with open(macaroon_path, 'rb') as f:
|
||||
macaroon_bytes = f.read()
|
||||
macaroon = codecs.encode(macaroon_bytes, 'hex')
|
||||
|
||||
# build ssl credentials using the cert the same as before
|
||||
cert_creds = grpc.ssl_channel_credentials(cert)
|
||||
|
||||
# now build meta data credentials
|
||||
auth_creds = grpc.metadata_call_credentials(metadata_callback)
|
||||
|
||||
# combine the cert credentials and the macaroon auth credentials
|
||||
# such that every call is properly encrypted and authenticated
|
||||
combined_creds = grpc.composite_channel_credentials(cert_creds, auth_creds)
|
||||
|
||||
# finally pass in the combined credentials when creating a channel
|
||||
return grpc.secure_channel('{}:{}'.format(host, port), combined_creds)
|
||||
|
||||
|
||||
def build_macaroon_path(name=None, network="bitcoin", chain="main"):
|
||||
if not name.lower() in MACAROON_LIST:
|
||||
raise Exception("name must be one of: {}".format(", ".join(MACAROON_LIST)))
|
||||
|
||||
macaroon_path = os.path.expanduser('~/.lnd/data/chain/{}/{}net/{}.macaroon'.format(network, chain, name.lower()))
|
||||
assert isfile(macaroon_path) and os.access(macaroon_path, os.R_OK), \
|
||||
"File {} doesn't exist or isn't readable".format(macaroon_path)
|
||||
|
||||
return macaroon_path
|
||||
|
||||
|
||||
def check_lnd(stub, proc_name="lnd", rpc_listen_ports=None):
|
||||
if not rpc_listen_ports:
|
||||
rpc_listen_ports = [10009]
|
||||
|
||||
pid_ok = False
|
||||
listen_ok = False
|
||||
unlocked = False
|
||||
synced_to_chain = False
|
||||
synced_to_graph = False
|
||||
|
||||
if IS_WIN32_ENV:
|
||||
return pid_ok, listen_ok, unlocked, synced_to_chain, synced_to_graph
|
||||
|
||||
if not [p.info for p in psutil.process_iter(attrs=['pid', 'name']) if proc_name in p.info['name']]:
|
||||
return pid_ok, listen_ok, unlocked, synced_to_chain, synced_to_graph
|
||||
else:
|
||||
pid_ok = True
|
||||
|
||||
if not [net_con for net_con in psutil.net_connections(kind='inet')
|
||||
if (net_con.status == psutil.CONN_LISTEN and net_con.laddr[1] in rpc_listen_ports)]:
|
||||
return pid_ok, listen_ok, unlocked, synced_to_chain, synced_to_graph
|
||||
else:
|
||||
listen_ok = True
|
||||
|
||||
try:
|
||||
get_info = stub.GetInfo(ln.GetInfoRequest())
|
||||
unlocked = True
|
||||
synced_to_chain = get_info.synced_to_chain
|
||||
synced_to_graph = get_info.synced_to_graph
|
||||
|
||||
except grpc.RpcError as err:
|
||||
if err._state.__dict__['code'] == grpc.StatusCode.UNIMPLEMENTED:
|
||||
log.debug("wallet is 'locked'")
|
||||
else:
|
||||
log.warning("an unknown RpcError occurred")
|
||||
log.warning(err)
|
||||
|
||||
except Exception as err:
|
||||
log.warning("an error occurred: {}".format(err))
|
||||
|
||||
return pid_ok, listen_ok, unlocked, synced_to_chain, synced_to_graph
|
||||
|
||||
|
||||
def check_lnd_channels(stub):
|
||||
"""let's assume that check_lnd() was called just before calling this"""
|
||||
total_active_channels = 0
|
||||
total_remote_balance_sat = 0
|
||||
|
||||
try:
|
||||
request = ln.ListChannelsRequest(
|
||||
active_only=True,
|
||||
inactive_only=False,
|
||||
public_only=False,
|
||||
private_only=False,
|
||||
)
|
||||
response = stub.ListChannels(request)
|
||||
|
||||
total_active_channels = len(response.channels)
|
||||
for channel in response.channels:
|
||||
# log.debug(channel)
|
||||
total_remote_balance_sat += channel.remote_balance
|
||||
|
||||
except grpc.RpcError as err:
|
||||
if err._state.__dict__['code'] == grpc.StatusCode.UNIMPLEMENTED:
|
||||
log.debug("wallet is 'locked'")
|
||||
else:
|
||||
log.warning("an unknown RpcError occurred")
|
||||
log.warning(err)
|
||||
|
||||
except Exception as err:
|
||||
log.warning("an error occurred: {}".format(err))
|
||||
|
||||
return total_active_channels, total_remote_balance_sat
|
||||
|
||||
|
||||
def check_invoice_paid(stub, invoice_r_hash, num_max_invoices=3):
|
||||
# ToDo error handling
|
||||
request = ln.ListInvoiceRequest(num_max_invoices=num_max_invoices, reversed=True)
|
||||
response = stub.ListInvoices(request)
|
||||
|
||||
for invoice in response.invoices:
|
||||
hex_str = convert_r_hash_hex_bytes(invoice.r_hash)
|
||||
|
||||
if hex_str == invoice_r_hash:
|
||||
if invoice.settled:
|
||||
log.debug("found - and settled: {}".format(invoice))
|
||||
amt_paid_sat = invoice.amt_paid_sat
|
||||
return True, amt_paid_sat
|
||||
else:
|
||||
log.debug("found - but NOT settled.")
|
||||
return False, None
|
||||
else:
|
||||
log.warning("invoice NOT found")
|
||||
return False, None
|
||||
|
||||
|
||||
def create_invoice(stub, memo="", value=0):
|
||||
# ToDo error handling
|
||||
request = ln.Invoice(memo=memo, value=value)
|
||||
response = stub.AddInvoice(request)
|
||||
return response
|
||||
|
||||
|
||||
def get_node_uri(stub):
|
||||
# ToDo error handling
|
||||
response = stub.GetInfo(ln.GetInfoRequest())
|
||||
if response.uris:
|
||||
return response.uris[0]
|
||||
|
||||
|
||||
def main():
|
||||
network = "bitcoin"
|
||||
chain = "main"
|
||||
|
||||
stub_readonly = ReadOnlyStub(network=network, chain=chain)
|
||||
pid_ok, listen_ok, unlocked, synced_to_chain, synced_to_graph = check_lnd(stub_readonly)
|
||||
print(pid_ok, listen_ok, unlocked, synced_to_chain, synced_to_graph)
|
||||
|
||||
if pid_ok and listen_ok and unlocked:
|
||||
node_uri = get_node_uri(stub_readonly)
|
||||
print("Node URI: {}".format(node_uri))
|
||||
|
||||
num, sats = check_lnd_channels(stub_readonly)
|
||||
print("Total Channels: {}".format(num))
|
||||
print("Total Remote Capacity: {}".format(sats))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
195
home.admin/BlitzTUI/blitztui/config.py
Normal file
@ -0,0 +1,195 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
import os
|
||||
from configparser import ConfigParser, DEFAULTSECT
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LndConfig(object):
|
||||
def __init__(self, abs_path="/mnt/hdd/lnd/lnd.conf"):
|
||||
self.abs_path = abs_path
|
||||
|
||||
# default values for LND Configuration
|
||||
self.rpc_listen = ""
|
||||
|
||||
@property
|
||||
def rpc_listen_host(self):
|
||||
return self.rpc_listen.split(":")[0]
|
||||
|
||||
@property
|
||||
def rpc_listen_port(self):
|
||||
try:
|
||||
return int(self.rpc_listen.split(":")[1])
|
||||
except (IndexError, TypeError, ValueError):
|
||||
return 0
|
||||
|
||||
def reload(self):
|
||||
"""load config from file"""
|
||||
parser = ConfigParser()
|
||||
|
||||
log.debug("loading config from file: {}".format(self.abs_path))
|
||||
with open(self.abs_path) as f:
|
||||
parser.read_string(f.read())
|
||||
|
||||
app_options = parser["Application Options"]
|
||||
|
||||
self.rpc_listen = get_str_clean(app_options, "rpclisten", self.rpc_listen)
|
||||
|
||||
|
||||
class RaspiBlitzConfig(object):
|
||||
def __init__(self, abs_path="/mnt/hdd/raspiblitz.conf"):
|
||||
self.abs_path = abs_path
|
||||
|
||||
# default values for RaspiBlitz Configuration
|
||||
self.auto_nat_discovery = False
|
||||
self.auto_pilot = False
|
||||
self.auto_unlock = False
|
||||
self.chain = ""
|
||||
self.dynDomain = ""
|
||||
self.dyn_update_url = ""
|
||||
self.hostname = ""
|
||||
self.invoice_allow_donations = False
|
||||
self.invoice_default_amount = 402
|
||||
self.lcd_rotate = False
|
||||
self.lnd_address = ""
|
||||
self.lnd_port = ""
|
||||
self.network = ""
|
||||
self.public_ip = ""
|
||||
self.rtl_web_interface = False
|
||||
self.run_behind_tor = False
|
||||
self.ssh_tunnel = ""
|
||||
self.touchscreen = False
|
||||
self.version = ""
|
||||
|
||||
def reload(self):
|
||||
"""load config from file"""
|
||||
parser = ConfigParser()
|
||||
|
||||
log.debug("loading config from file: {}".format(self.abs_path))
|
||||
with open(self.abs_path) as f:
|
||||
parser.read_string("[{}]\n".format(DEFAULTSECT) + f.read())
|
||||
|
||||
default_s = parser[DEFAULTSECT]
|
||||
|
||||
self.auto_nat_discovery = default_s.getboolean("autoNatDiscovery", self.auto_nat_discovery)
|
||||
self.auto_pilot = default_s.getboolean("autoPilot", self.auto_pilot)
|
||||
self.auto_unlock = default_s.getboolean("autoUnlock", self.auto_unlock)
|
||||
self.chain = get_str_clean(default_s, "chain", self.chain)
|
||||
self.dynDomain = get_str_clean(default_s, "dynDomain", self.dynDomain)
|
||||
self.dyn_update_url = get_str_clean(default_s, "dynUpdateUrl", self.dyn_update_url)
|
||||
self.hostname = get_str_clean(default_s, "hostname", self.hostname)
|
||||
self.invoice_allow_donations = default_s.getboolean("invoiceAllowDonations", self.invoice_allow_donations)
|
||||
self.invoice_default_amount = get_int_safe(default_s, "invoiceDefaultAmount", self.invoice_default_amount)
|
||||
self.lcd_rotate = default_s.getboolean("lcdrotate", self.lcd_rotate)
|
||||
self.lnd_address = get_str_clean(default_s, "lndAddress", self.lnd_address)
|
||||
self.lnd_port = get_str_clean(default_s, "lndPort", self.lnd_port)
|
||||
self.network = get_str_clean(default_s, "network", self.network)
|
||||
self.public_ip = get_str_clean(default_s, "publicIP", self.public_ip)
|
||||
self.rtl_web_interface = default_s.getboolean("rtlWebinterface", self.rtl_web_interface)
|
||||
self.run_behind_tor = default_s.getboolean("runBehindTor", self.run_behind_tor)
|
||||
self.ssh_tunnel = get_str_clean(default_s, "sshtunnel", self.ssh_tunnel)
|
||||
self.touchscreen = default_s.getboolean("touchscreen", self.touchscreen)
|
||||
self.version = get_str_clean(default_s, "raspiBlitzVersion", self.version)
|
||||
|
||||
|
||||
class RaspiBlitzInfo(object):
|
||||
def __init__(self, abs_path="/home/admin/raspiblitz.info"):
|
||||
self.abs_path = abs_path
|
||||
|
||||
# default values for RaspiBlitz Info
|
||||
self.base_image = ""
|
||||
self.chain = ""
|
||||
self.message = ""
|
||||
self.network = ""
|
||||
self.setup_step = 0
|
||||
self.state = ""
|
||||
self.undervoltage_reports = 0
|
||||
|
||||
def reload(self):
|
||||
"""load config from file"""
|
||||
parser = ConfigParser()
|
||||
|
||||
log.debug("loading config from file: {}".format(self.abs_path))
|
||||
with open(self.abs_path) as f:
|
||||
parser.read_string("[{}]\n".format(DEFAULTSECT) + f.read())
|
||||
|
||||
default_s = parser[DEFAULTSECT]
|
||||
|
||||
self.base_image = get_str_clean(default_s, "baseimage", self.base_image)
|
||||
self.chain = get_str_clean(default_s, "chain", self.chain)
|
||||
self.message = get_str_clean(default_s, "message", self.message)
|
||||
self.network = get_str_clean(default_s, "network", self.network)
|
||||
self.setup_step = get_int_safe(default_s, "setupStep", self.setup_step)
|
||||
self.state = get_str_clean(default_s, "state", self.state)
|
||||
self.undervoltage_reports = get_int_safe(default_s, "undervoltageReports", self.undervoltage_reports)
|
||||
|
||||
|
||||
def get_int_safe(cp_section, key, default_value):
|
||||
"""take a ConfigParser section, get key that might be string encoded int and return int"""
|
||||
try:
|
||||
value = cp_section.getint(key, default_value)
|
||||
except ValueError:
|
||||
_value = cp_section.get(key)
|
||||
value = int(_value.strip("'").strip('"')) # this will raise an Exception if int() fails!
|
||||
return value
|
||||
|
||||
|
||||
def get_str_clean(cp_section, key, default_value):
|
||||
"""take a ConfigParser section, get key and strip leading and trailing \' and \" chars"""
|
||||
value = cp_section.get(key, default_value)
|
||||
if not value:
|
||||
return ""
|
||||
|
||||
return value.lstrip('"').lstrip("'").rstrip('"').rstrip("'")
|
||||
|
||||
|
||||
def main():
|
||||
lnd_cfg = LndConfig()
|
||||
if os.path.exists(lnd_cfg.abs_path):
|
||||
lnd_cfg.reload()
|
||||
|
||||
print("=======\n= LND =\n=======")
|
||||
print("rpc_list: \t\t{}".format(lnd_cfg.rpc_listen))
|
||||
print("rpc_list_host: \t\t{}".format(lnd_cfg.rpc_listen_host))
|
||||
print("rpc_list_port: \t\t{}".format(lnd_cfg.rpc_listen_port))
|
||||
print("")
|
||||
|
||||
rb_cfg = RaspiBlitzConfig()
|
||||
if os.path.exists(rb_cfg.abs_path):
|
||||
rb_cfg.reload()
|
||||
|
||||
print("====================\n= RaspiBlitzConfig =\n====================")
|
||||
print("auto_nat_discovery: \t\t{}".format(rb_cfg.auto_nat_discovery))
|
||||
print("auto_pilot: \t\t\t{}".format(rb_cfg.auto_pilot))
|
||||
print("auto_unlock: \t\t\t{}".format(rb_cfg.auto_unlock))
|
||||
print("chain: \t\t\t\t{}".format(rb_cfg.chain))
|
||||
print("dynDomain: \t\t\t{}".format(rb_cfg.dynDomain))
|
||||
print("dyn_update_url: \t\t{}".format(rb_cfg.dyn_update_url))
|
||||
print("hostname: \t\t\t{}".format(rb_cfg.hostname))
|
||||
print("invoice_allow_donations: \t{}".format(rb_cfg.invoice_allow_donations))
|
||||
print("invoice_default_amount: \t{}".format(rb_cfg.invoice_default_amount))
|
||||
print("lcd_rotate: \t\t\t{}".format(rb_cfg.lcd_rotate))
|
||||
print("lnd_address: \t\t\t{}".format(rb_cfg.lnd_address))
|
||||
print("lnd_port: \t\t\t{}".format(rb_cfg.lnd_port))
|
||||
print("network: \t\t\t{}".format(rb_cfg.network))
|
||||
print("public_ip: \t\t\t{}".format(rb_cfg.public_ip))
|
||||
print("rtl_web_interface: \t\t{}".format(rb_cfg.rtl_web_interface))
|
||||
print("run_behind_tor: \t\t{}".format(rb_cfg.run_behind_tor))
|
||||
print("ssh_tunnel: \t\t\t{}".format(rb_cfg.ssh_tunnel))
|
||||
print("touchscreen: \t\t\t{}".format(rb_cfg.touchscreen))
|
||||
print("version: \t\t\t{}".format(rb_cfg.version))
|
||||
print("")
|
||||
|
||||
rb_info = RaspiBlitzInfo()
|
||||
if os.path.exists(rb_info.abs_path):
|
||||
rb_info.reload()
|
||||
|
||||
print("==================\n= RaspiBlitzInfo =\n==================")
|
||||
print("state: \t\t{}".format(rb_info.state))
|
||||
print("")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
48
home.admin/BlitzTUI/blitztui/file_logger.py
Normal file
@ -0,0 +1,48 @@
|
||||
import json
|
||||
import logging
|
||||
import logging.config
|
||||
import os
|
||||
import sys
|
||||
|
||||
IS_WIN32_ENV = sys.platform == "win32"
|
||||
|
||||
|
||||
def setup_logging(default_path=os.path.abspath(os.path.expanduser('~/.blitz-tui.json'))):
|
||||
"""Setup logging configuration"""
|
||||
path = default_path
|
||||
if os.path.exists(path):
|
||||
with open(path, 'rt') as f:
|
||||
config = json.load(f)
|
||||
logging.config.dictConfig(config)
|
||||
|
||||
else: # if $default_path does not exist use the following default log setup
|
||||
|
||||
if IS_WIN32_ENV:
|
||||
log_file = "blitz-tui.log"
|
||||
else:
|
||||
log_file = os.path.abspath(os.path.expanduser('~/blitz-tui.log'))
|
||||
|
||||
default_config_as_dict = dict(
|
||||
version=1,
|
||||
disable_existing_loggers=False,
|
||||
formatters={'simple': {'format': '%(asctime)s - %(levelname)s - %(message)s'},
|
||||
'extended': {
|
||||
'format': '%(asctime)s - %(name)s - %(levelname)s - %(module)s:%(lineno)d - %(message)s'}},
|
||||
handlers={'console': {'class': 'logging.StreamHandler',
|
||||
'level': 'INFO',
|
||||
'formatter': 'extended',
|
||||
'stream': 'ext://sys.stdout'},
|
||||
'file_handler': {'class': 'logging.handlers.RotatingFileHandler',
|
||||
'level': 'DEBUG',
|
||||
'formatter': 'extended',
|
||||
'filename': log_file,
|
||||
'maxBytes': 10485760,
|
||||
'backupCount': 0,
|
||||
'encoding': 'utf8'}},
|
||||
loggers={'infoblitz': {'level': 'DEBUG',
|
||||
'handlers': ['console', 'file_handler'],
|
||||
'propagate': 'no'}},
|
||||
root={'level': 'DEBUG', 'handlers': ['console', 'file_handler']}
|
||||
)
|
||||
|
||||
logging.config.dictConfig(default_config_as_dict)
|
45
home.admin/BlitzTUI/blitztui/file_watcher.py
Normal file
@ -0,0 +1,45 @@
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from PyQt5.QtCore import QThread, pyqtSignal
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
if sys.platform == "win32":
|
||||
log.info("skipping inotify on win32 as it is not supported")
|
||||
else:
|
||||
import inotify.adapters
|
||||
import inotify.constants
|
||||
|
||||
|
||||
class FileWatcherThread(QThread):
|
||||
signal = pyqtSignal()
|
||||
|
||||
def __init__(self, dir_names, file_names, *args, **kwargs):
|
||||
QThread.__init__(self, *args, **kwargs)
|
||||
self.dir_names = dir_names
|
||||
self.file_names = file_names
|
||||
|
||||
def run(self):
|
||||
# run method gets called when we start the thread
|
||||
if sys.platform == "win32":
|
||||
log.info("skipping inotify on win32 as it is not supported")
|
||||
return
|
||||
|
||||
log.info("starting config watcher")
|
||||
i = inotify.adapters.Inotify()
|
||||
|
||||
mask = inotify.constants.IN_MODIFY | inotify.constants.IN_CLOSE_WRITE
|
||||
|
||||
for dir_name in self.dir_names:
|
||||
i.add_watch(dir_name, mask=mask)
|
||||
|
||||
for event in i.event_gen(yield_nones=False):
|
||||
_, type_names, path, filename = event
|
||||
|
||||
log.debug("PATH=[{}] FILENAME=[{}] EVENT_TYPES={}".format(
|
||||
path, filename, type_names))
|
||||
|
||||
if path in self.dir_names and filename in self.file_names:
|
||||
log.info("watched file was modified/touched")
|
||||
self.signal.emit()
|
646
home.admin/BlitzTUI/blitztui/main.py
Normal file
@ -0,0 +1,646 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import argparse
|
||||
import itertools
|
||||
import logging
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
import time
|
||||
from argparse import RawTextHelpFormatter
|
||||
from functools import lru_cache
|
||||
from io import BytesIO
|
||||
from threading import Event
|
||||
|
||||
import qrcode
|
||||
from PyQt5.QtCore import Qt, QProcess, QThread, pyqtSignal, QCoreApplication, QTimer, QEventLoop
|
||||
from PyQt5.QtGui import QPixmap
|
||||
from PyQt5.QtWidgets import QMainWindow, QApplication, QDialog, QDialogButtonBox
|
||||
from blitztui.client import ReadOnlyStub, InvoiceStub
|
||||
from blitztui.client import check_lnd, check_lnd_channels
|
||||
from blitztui.client import check_invoice_paid, create_invoice, get_node_uri
|
||||
from blitztui.client import convert_r_hash_hex_bytes
|
||||
from blitztui.config import LndConfig, RaspiBlitzConfig, RaspiBlitzInfo
|
||||
from blitztui.file_watcher import FileWatcherThread
|
||||
from blitztui.memo import adjective_noun_pair
|
||||
from blitztui.version import __version__
|
||||
from blitztui.ui.home import Ui_MainWindow
|
||||
from blitztui.ui.invoice import Ui_DialogSelectInvoice
|
||||
from blitztui.ui.off import Ui_DialogConfirmOff
|
||||
from blitztui.ui.qcode import Ui_DialogShowQrCode
|
||||
from pyqtspinner.spinner import WaitingSpinner
|
||||
|
||||
log = logging.getLogger()
|
||||
|
||||
IS_DEV_ENV = os.getenv('RASPIBLITZ_DEV', '0').lower() in ['1', 'true', 't', 'y', 'yes', 'on']
|
||||
IS_WIN32_ENV = sys.platform == "win32"
|
||||
|
||||
SCREEN_HEIGHT = 318
|
||||
|
||||
LND_CONF = "/mnt/hdd/lnd/lnd.conf"
|
||||
RB_CONF = "/mnt/hdd/raspiblitz.conf"
|
||||
RB_INFO = "/home/admin/raspiblitz.info"
|
||||
|
||||
STATUS_INTERVAL_LND = 30
|
||||
STATUS_INTERVAL_LND_CHANNELS = 120
|
||||
INVOICE_CHECK_TIMEOUT = 1800
|
||||
INVOICE_CHECK_INTERVAL = 2.0 # 1800*2.0s == 3600s == 1 Hour during which the invoice is monitored
|
||||
|
||||
SCREEN_NODE_URI = "Node URI"
|
||||
SCREEN_INVOICE = "Invoice"
|
||||
|
||||
|
||||
class AppWindow(QMainWindow):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AppWindow, self).__init__(*args, **kwargs)
|
||||
self.ui = Ui_MainWindow()
|
||||
self.ui.setupUi(self)
|
||||
|
||||
# translations..?!
|
||||
self._translate = QCoreApplication.translate
|
||||
|
||||
if IS_WIN32_ENV:
|
||||
log.info("using dummy config on win32")
|
||||
lnd_cfg_abs_path = os.path.join(os.path.dirname(__file__), "..", "data", os.path.basename(LND_CONF))
|
||||
rb_cfg_abs_path = os.path.join(os.path.dirname(__file__), "..", "data", os.path.basename(RB_CONF))
|
||||
rb_info_abs_path = os.path.join(os.path.dirname(__file__), "..", "data", os.path.basename(RB_INFO))
|
||||
else:
|
||||
lnd_cfg_abs_path = LND_CONF
|
||||
rb_cfg_abs_path = RB_CONF
|
||||
rb_info_abs_path = RB_INFO
|
||||
|
||||
# read config and info files
|
||||
if not os.path.exists(lnd_cfg_abs_path):
|
||||
raise Exception("file does not exist: {}".format(lnd_cfg_abs_path))
|
||||
|
||||
if not os.path.exists(rb_cfg_abs_path):
|
||||
raise Exception("file does not exist: {}".format(rb_cfg_abs_path))
|
||||
|
||||
if not os.path.exists(rb_info_abs_path):
|
||||
raise Exception("file does not exist: {}".format(rb_info_abs_path))
|
||||
|
||||
self.lnd_cfg = LndConfig(lnd_cfg_abs_path)
|
||||
self.lnd_cfg.reload()
|
||||
|
||||
self.rb_cfg = RaspiBlitzConfig(rb_cfg_abs_path)
|
||||
self.rb_cfg.reload()
|
||||
|
||||
self.rb_info = RaspiBlitzInfo(rb_info_abs_path)
|
||||
self.rb_info.reload()
|
||||
|
||||
# initialize attributes
|
||||
self.invoice_to_check = None
|
||||
self.invoice_to_check_flag = None
|
||||
|
||||
self.uptime = 0
|
||||
|
||||
self.status_lnd_due = 0
|
||||
self.status_lnd_interval = STATUS_INTERVAL_LND
|
||||
self.status_lnd_pid_ok = False
|
||||
self.status_lnd_listen_ok = False
|
||||
self.status_lnd_unlocked = False
|
||||
self.status_lnd_synced_to_chain = False
|
||||
self.status_lnd_synced_to_graph = False
|
||||
|
||||
self.status_lnd_channel_due = 0
|
||||
self.status_lnd_channel_interval = STATUS_INTERVAL_LND_CHANNELS
|
||||
self.status_lnd_channel_total_active = 0
|
||||
self.status_lnd_channel_total_remote_balance = 0
|
||||
|
||||
# initial updates
|
||||
self.update_uptime()
|
||||
self.update_status_lnd()
|
||||
self.update_status_lnd_channels()
|
||||
|
||||
# initial update of Main Window Title Bar
|
||||
self.update_title_bar()
|
||||
|
||||
# Align Main Window Top Left
|
||||
self.move(0, 0)
|
||||
|
||||
# set as maximized (unless on Windows dev host)
|
||||
if IS_WIN32_ENV:
|
||||
log.info("not maximizing window on win32")
|
||||
else:
|
||||
self.setWindowState(Qt.WindowMaximized)
|
||||
|
||||
# Bindings: buttons
|
||||
self.ui.pushButton_1.clicked.connect(self.on_button_1_clicked)
|
||||
self.ui.pushButton_2.clicked.connect(self.on_button_2_clicked)
|
||||
self.ui.pushButton_3.clicked.connect(self.on_button_3_clicked)
|
||||
self.ui.pushButton_4.clicked.connect(self.on_button_4_clicked)
|
||||
|
||||
# disable button 1 for now
|
||||
self.ui.pushButton_1.setEnabled(False)
|
||||
|
||||
# connect error dismiss button and hide for start
|
||||
self.ui.buttonBox_close.button(QDialogButtonBox.Close).setText("Ok")
|
||||
self.ui.buttonBox_close.button(QDialogButtonBox.Close).clicked.connect(self.hide_error)
|
||||
self.hide_error()
|
||||
|
||||
# Show QR Code Dialog Windows
|
||||
self.w_qr_code = QDialog(flags=(Qt.Dialog | Qt.FramelessWindowHint))
|
||||
self.ui_qr_code = Ui_DialogShowQrCode()
|
||||
self.ui_qr_code.setupUi(self.w_qr_code)
|
||||
self.w_qr_code.move(0, 0)
|
||||
|
||||
# SPINNER for CR Code Dialog Window
|
||||
self.ui_qr_code.spinner = WaitingSpinner(self.w_qr_code)
|
||||
|
||||
self.beat_thread = BeatThread()
|
||||
self.beat_thread.signal.connect(self.process_beat)
|
||||
self.beat_thread.start()
|
||||
|
||||
self.generate_qr_code_thread = GenerateQrCodeThread()
|
||||
self.generate_qr_code_thread.signal.connect(self.generate_qr_code_finished)
|
||||
|
||||
self.file_watcher = FileWatcherThread(
|
||||
dir_names=[os.path.dirname(LND_CONF), os.path.dirname(RB_CONF), os.path.dirname(RB_INFO)],
|
||||
file_names=[os.path.basename(LND_CONF), os.path.basename(RB_CONF), os.path.basename(RB_INFO)],
|
||||
)
|
||||
self.file_watcher.signal.connect(self.update_watched_attr)
|
||||
self.file_watcher.start()
|
||||
|
||||
# finally start 00infoBlitz.sh in dedicated xterm frame
|
||||
self.start_info_lcd()
|
||||
|
||||
self.show()
|
||||
|
||||
def start_info_lcd(self, pause=12):
|
||||
# if system has been running for more than 90 seconds then skip pause
|
||||
if self.uptime > 90:
|
||||
pause = 0
|
||||
|
||||
process = QProcess(self)
|
||||
process.setProcessChannelMode(QProcess.MergedChannels)
|
||||
# connect the stdout_item to the Process StandardOutput
|
||||
# it gets constantly update as the process emit std output
|
||||
process.readyReadStandardOutput.connect(
|
||||
lambda: log.info(str(process.readAllStandardOutput().data().decode('utf-8'))))
|
||||
|
||||
process.start('xterm', ['-fn', 'fixed', '-into', str(int(self.ui.widget.winId())),
|
||||
'+sb', '-hold', '-e', 'bash -c \"/home/admin/00infoLCD.sh --pause {}\"'.format(pause)])
|
||||
|
||||
def check_invoice(self, flag, tick=0):
|
||||
log.info("checking invoice paid (Tick: {})".format(tick))
|
||||
self.invoice_to_check_flag = flag
|
||||
|
||||
if tick >= INVOICE_CHECK_TIMEOUT:
|
||||
log.debug("canceled checking invoice paid")
|
||||
flag.set()
|
||||
|
||||
if IS_DEV_ENV:
|
||||
res = False
|
||||
amt_paid_sat = 123123402
|
||||
|
||||
if tick == 5:
|
||||
res = True
|
||||
|
||||
else:
|
||||
stub_readonly = ReadOnlyStub(network=self.rb_cfg.network, chain=self.rb_cfg.chain)
|
||||
res, amt_paid_sat = check_invoice_paid(stub_readonly, self.invoice_to_check)
|
||||
log.debug("result of invoice check: {}".format(res))
|
||||
|
||||
if res:
|
||||
log.debug("paid!")
|
||||
self.ui_qr_code.qcode.setMargin(8)
|
||||
self.ui_qr_code.qcode.setPixmap(QPixmap(":/RaspiBlitz/images/Paid_Stamp.png"))
|
||||
|
||||
if amt_paid_sat:
|
||||
self.ui_qr_code.status_value.setText("Paid")
|
||||
self.ui_qr_code.amt_paid_value.setText("{}".format(amt_paid_sat))
|
||||
else:
|
||||
self.ui_qr_code.status_value.setText("Paid")
|
||||
|
||||
flag.set()
|
||||
|
||||
def update_status_lnd(self):
|
||||
if IS_WIN32_ENV:
|
||||
return
|
||||
|
||||
# log.debug("update_status_lnd due: {}".format(self.status_lnd_due))
|
||||
if self.status_lnd_due <= self.uptime:
|
||||
log.debug("updating status_lnd")
|
||||
stub_readonly = ReadOnlyStub(network=self.rb_cfg.network, chain=self.rb_cfg.chain)
|
||||
pid_ok, listen_ok, unlocked, synced_to_chain, synced_to_graph = check_lnd(stub_readonly)
|
||||
self.status_lnd_pid_ok = pid_ok
|
||||
self.status_lnd_listen_ok = listen_ok
|
||||
self.status_lnd_unlocked = unlocked
|
||||
self.status_lnd_synced_to_chain = synced_to_chain
|
||||
self.status_lnd_synced_to_graph = synced_to_graph
|
||||
# set next due time
|
||||
self.status_lnd_due = self.uptime + self.status_lnd_interval
|
||||
|
||||
def update_status_lnd_channels(self):
|
||||
if IS_WIN32_ENV:
|
||||
return
|
||||
|
||||
# log.debug("update_status_lnd_channel due: {}".format(self.status_lnd_channel_due))
|
||||
if self.status_lnd_channel_due <= self.uptime:
|
||||
log.debug("updating status_lnd_channels")
|
||||
stub_readonly = ReadOnlyStub(network=self.rb_cfg.network, chain=self.rb_cfg.chain)
|
||||
self.status_lnd_channel_total_active, self.status_lnd_channel_total_remote_balance = \
|
||||
check_lnd_channels(stub_readonly)
|
||||
# set next due time
|
||||
self.status_lnd_channel_due = self.uptime + self.status_lnd_channel_interval
|
||||
|
||||
def update_title_bar(self):
|
||||
log.debug("updating: Main Window Title Bar")
|
||||
self.setWindowTitle(self._translate("MainWindow", "RaspiBlitz v{} - {} - {}net".format(self.rb_cfg.version,
|
||||
self.rb_cfg.network,
|
||||
self.rb_cfg.chain)))
|
||||
|
||||
def update_uptime(self):
|
||||
if IS_WIN32_ENV:
|
||||
self.uptime += 1
|
||||
else:
|
||||
with open('/proc/uptime', 'r') as f:
|
||||
self.uptime = float(f.readline().split()[0])
|
||||
# log.info("Uptime: {}".format(self.uptime))
|
||||
|
||||
def process_beat(self, _):
|
||||
self.update_uptime()
|
||||
self.update_status_lnd()
|
||||
self.update_status_lnd_channels()
|
||||
|
||||
def update_watched_attr(self):
|
||||
log.debug("updating: watched attributes")
|
||||
self.lnd_cfg.reload()
|
||||
self.rb_cfg.reload()
|
||||
self.rb_info.reload()
|
||||
|
||||
# add anything here that should be updated now too
|
||||
self.update_title_bar()
|
||||
|
||||
def hide_error(self):
|
||||
self.ui.error_label.hide()
|
||||
self.ui.buttonBox_close.hide()
|
||||
|
||||
def show_qr_code(self, data, screen=None, memo=None, status=None, inv_amt=None, amt_paid="N/A"):
|
||||
log.debug("show_qr_code: {}".format(data))
|
||||
# reset to logo and set text
|
||||
self.ui_qr_code.qcode.setMargin(48)
|
||||
self.ui_qr_code.qcode.setPixmap(QPixmap(":/RaspiBlitz/images/RaspiBlitz_Logo_Stacked.png"))
|
||||
|
||||
if screen == SCREEN_NODE_URI:
|
||||
self.ui_qr_code.memo_key.show()
|
||||
self.ui_qr_code.memo_key.setText("Node URI")
|
||||
|
||||
_tmp = data.split("@")
|
||||
pub = _tmp[0]
|
||||
_tmp2 = _tmp[1].split(":")
|
||||
host = _tmp2[0]
|
||||
port = _tmp2[1]
|
||||
|
||||
n = 16
|
||||
pub = [(pub[i:i + n]) for i in range(0, len(pub), n)]
|
||||
host = [(host[i:i + n]) for i in range(0, len(host), n)]
|
||||
self.ui_qr_code.memo_value.show()
|
||||
self.ui_qr_code.memo_value.setText("{} \n@\n{} \n:{}".format(" ".join(pub), " ".join(host), port))
|
||||
|
||||
self.ui_qr_code.status_key.hide()
|
||||
self.ui_qr_code.status_value.hide()
|
||||
self.ui_qr_code.inv_amt_key.hide()
|
||||
self.ui_qr_code.inv_amt_value.hide()
|
||||
self.ui_qr_code.amt_paid_key.hide()
|
||||
self.ui_qr_code.amt_paid_value.hide()
|
||||
|
||||
if screen == SCREEN_INVOICE:
|
||||
self.ui_qr_code.memo_key.show()
|
||||
self.ui_qr_code.memo_key.setText("Invoice Memo")
|
||||
|
||||
self.ui_qr_code.memo_value.show()
|
||||
self.ui_qr_code.memo_value.setText(memo)
|
||||
|
||||
self.ui_qr_code.status_key.show()
|
||||
self.ui_qr_code.status_value.show()
|
||||
self.ui_qr_code.status_value.setText(status)
|
||||
|
||||
self.ui_qr_code.inv_amt_key.show()
|
||||
self.ui_qr_code.inv_amt_value.show()
|
||||
self.ui_qr_code.inv_amt_value.setText("{}".format(inv_amt))
|
||||
|
||||
self.ui_qr_code.amt_paid_key.show()
|
||||
self.ui_qr_code.amt_paid_value.show()
|
||||
self.ui_qr_code.amt_paid_value.setText("{}".format(amt_paid))
|
||||
|
||||
# set function and start thread
|
||||
self.generate_qr_code_thread.data = data
|
||||
self.generate_qr_code_thread.start()
|
||||
self.ui_qr_code.spinner.start()
|
||||
|
||||
self.w_qr_code.activateWindow()
|
||||
self.w_qr_code.show()
|
||||
|
||||
rsp = self.w_qr_code.exec_()
|
||||
if rsp == QDialog.Accepted:
|
||||
log.info("QR: pressed OK - canceling invoice check")
|
||||
if self.invoice_to_check_flag:
|
||||
self.invoice_to_check_flag.set()
|
||||
|
||||
def generate_qr_code_finished(self, img):
|
||||
buf = BytesIO()
|
||||
img.save(buf, "PNG")
|
||||
|
||||
qt_pixmap = QPixmap()
|
||||
qt_pixmap.loadFromData(buf.getvalue(), "PNG")
|
||||
self.ui_qr_code.spinner.stop()
|
||||
self.ui_qr_code.qcode.setMargin(2)
|
||||
self.ui_qr_code.qcode.setPixmap(qt_pixmap)
|
||||
|
||||
def on_button_1_clicked(self):
|
||||
log.debug("clicked: B1: {}".format(self.winId()))
|
||||
# self.start_info_lcd(pause=0)
|
||||
|
||||
def on_button_2_clicked(self):
|
||||
log.debug("clicked: B2: {}".format(self.winId()))
|
||||
|
||||
if not (self.status_lnd_pid_ok and self.status_lnd_listen_ok):
|
||||
log.warning("LND is not ready")
|
||||
self.ui.error_label.show()
|
||||
self.ui.error_label.setText("Err: LND is not ready!")
|
||||
self.ui.buttonBox_close.show()
|
||||
return
|
||||
|
||||
if not self.status_lnd_unlocked:
|
||||
log.warning("LND is locked")
|
||||
self.ui.error_label.show()
|
||||
self.ui.error_label.setText("Err: LND is locked")
|
||||
self.ui.buttonBox_close.show()
|
||||
return
|
||||
|
||||
data = self.get_node_uri()
|
||||
if data:
|
||||
self.show_qr_code(data, SCREEN_NODE_URI)
|
||||
else:
|
||||
log.warning("Node URI is none!")
|
||||
# TODO(frennkie) inform user
|
||||
|
||||
def on_button_3_clicked(self):
|
||||
log.debug("clicked: B3: {}".format(self.winId()))
|
||||
|
||||
if not (self.status_lnd_pid_ok and self.status_lnd_listen_ok):
|
||||
log.warning("LND is not ready")
|
||||
self.ui.error_label.show()
|
||||
self.ui.error_label.setText("Err: LND is not ready!")
|
||||
self.ui.buttonBox_close.show()
|
||||
return
|
||||
|
||||
if not self.status_lnd_unlocked:
|
||||
log.warning("LND is locked")
|
||||
self.ui.error_label.show()
|
||||
self.ui.error_label.setText("Err: LND is locked")
|
||||
self.ui.buttonBox_close.show()
|
||||
return
|
||||
|
||||
if not self.status_lnd_channel_total_active:
|
||||
log.warning("not creating invoice: unable to receive - no open channels")
|
||||
self.ui.error_label.show()
|
||||
self.ui.error_label.setText("Err: No open channels!")
|
||||
self.ui.buttonBox_close.show()
|
||||
return
|
||||
|
||||
if not self.status_lnd_channel_total_remote_balance:
|
||||
log.warning("not creating invoice: unable to receive - no remote capacity on any channel")
|
||||
self.ui.error_label.show()
|
||||
self.ui.error_label.setText("Err: No remote capacity!")
|
||||
self.ui.buttonBox_close.show()
|
||||
return
|
||||
|
||||
dialog_b1 = QDialog(flags=(Qt.Dialog | Qt.FramelessWindowHint))
|
||||
ui = Ui_DialogSelectInvoice()
|
||||
ui.setupUi(dialog_b1)
|
||||
|
||||
dialog_b1.move(0, 0)
|
||||
|
||||
ui.buttonBox.button(QDialogButtonBox.Yes).setText("{} SAT".format(self.rb_cfg.invoice_default_amount))
|
||||
ui.buttonBox.button(QDialogButtonBox.Ok).setText("Donation")
|
||||
if self.rb_cfg.invoice_allow_donations:
|
||||
ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True)
|
||||
else:
|
||||
ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
|
||||
|
||||
ui.buttonBox.button(QDialogButtonBox.Cancel).setText("Cancel")
|
||||
|
||||
ui.buttonBox.button(QDialogButtonBox.Yes).clicked.connect(self.b3_invoice_set_amt)
|
||||
ui.buttonBox.button(QDialogButtonBox.Ok).clicked.connect(self.b3_invoice_custom_amt)
|
||||
|
||||
dialog_b1.show()
|
||||
|
||||
rsp = dialog_b1.exec_()
|
||||
if not rsp == QDialog.Accepted:
|
||||
log.info("B3: pressed is: Cancel")
|
||||
|
||||
def b3_invoice_set_amt(self):
|
||||
log.info("b1 option: set amount")
|
||||
|
||||
check_invoice_thread = ClockStoppableThread(Event(), interval=INVOICE_CHECK_INTERVAL)
|
||||
check_invoice_thread.signal.connect(self.check_invoice)
|
||||
check_invoice_thread.start()
|
||||
|
||||
a, n = adjective_noun_pair()
|
||||
inv_memo = "RB-{}-{}".format(a.capitalize(), n.capitalize())
|
||||
|
||||
new_invoice = self.create_new_invoice(inv_memo, amt=self.rb_cfg.invoice_default_amount)
|
||||
data = new_invoice.payment_request
|
||||
self.show_qr_code(data, SCREEN_INVOICE, memo=inv_memo, status="Open",
|
||||
inv_amt=self.rb_cfg.invoice_default_amount)
|
||||
|
||||
def b3_invoice_custom_amt(self):
|
||||
log.info("b1 option: custom amount")
|
||||
|
||||
check_invoice_thread = ClockStoppableThread(Event(), interval=INVOICE_CHECK_INTERVAL)
|
||||
check_invoice_thread.signal.connect(self.check_invoice)
|
||||
check_invoice_thread.start()
|
||||
|
||||
a, n = adjective_noun_pair()
|
||||
inv_memo = "RB-{}-{}".format(a.capitalize(), n.capitalize())
|
||||
|
||||
new_invoice = self.create_new_invoice(inv_memo, amt=0)
|
||||
data = new_invoice.payment_request
|
||||
self.show_qr_code(data, SCREEN_INVOICE, memo=inv_memo, status="Open", inv_amt="Donation")
|
||||
|
||||
def on_button_4_clicked(self):
|
||||
log.debug("clicked: B4: {}".format(self.winId()))
|
||||
|
||||
dialog_b4 = QDialog(flags=(Qt.Dialog | Qt.FramelessWindowHint))
|
||||
ui = Ui_DialogConfirmOff()
|
||||
ui.setupUi(dialog_b4)
|
||||
|
||||
dialog_b4.move(0, 0)
|
||||
|
||||
ui.buttonBox.button(QDialogButtonBox.Yes).setText("Shutdown")
|
||||
ui.buttonBox.button(QDialogButtonBox.Retry).setText("Restart")
|
||||
ui.buttonBox.button(QDialogButtonBox.Cancel).setText("Cancel")
|
||||
|
||||
ui.buttonBox.button(QDialogButtonBox.Yes).clicked.connect(self.b4_shutdown)
|
||||
ui.buttonBox.button(QDialogButtonBox.Retry).clicked.connect(self.b4_restart)
|
||||
|
||||
dialog_b4.show()
|
||||
rsp = dialog_b4.exec_()
|
||||
|
||||
if rsp == QDialog.Accepted:
|
||||
log.info("B4: pressed is: Accepted - Shutdown or Restart")
|
||||
else:
|
||||
log.info("B4: pressed is: Cancel")
|
||||
|
||||
def b4_shutdown(self):
|
||||
log.info("shutdown")
|
||||
if IS_WIN32_ENV:
|
||||
log.info("skipping on win32")
|
||||
return
|
||||
|
||||
process = QProcess(self)
|
||||
process.start('xterm', ['-fn', 'fixed', '-into', str(int(self.ui.widget.winId())),
|
||||
'+sb', '-hold', '-e', 'bash -c \"sudo /home/admin/XXshutdown.sh\"'])
|
||||
|
||||
def b4_restart(self):
|
||||
log.info("restart")
|
||||
if IS_WIN32_ENV:
|
||||
log.info("skipping on win32")
|
||||
return
|
||||
|
||||
process = QProcess(self)
|
||||
process.start('xterm', ['-fn', 'fixed', '-into', str(int(self.ui.widget.winId())),
|
||||
'+sb', '-hold', '-e', 'bash -c \"sudo /home/admin/XXreboot.sh\"'])
|
||||
|
||||
def create_new_invoice(self, memo="Pay to RaspiBlitz", amt=0):
|
||||
if IS_DEV_ENV:
|
||||
# Fake an invoice for dev
|
||||
class FakeAddInvoiceResponse(object):
|
||||
def __init__(self):
|
||||
self.add_index = 145
|
||||
self.payment_request = "lnbc47110n1pwmfqcdpp5k55n5erv60mg6u4c8s3qggnw3dsn267e80ypjxxp6gj593" \
|
||||
"p3c25sdq9vehk7cqzpgprn0ytv6ukxc2vclgag38nmsmlyggmd4zand9qay2l3gc5at" \
|
||||
"ecxjynydyzhvxsysam9d46y5lgezh2nkufvn23403t3tz3lyhd070dgq625xp0"
|
||||
self.r_hash = b'\xf9\xe3(\xf5\x84\xdad\x88\xe4%\xa7\x1c\x95\xbe\x8baJ\x1c\xc1\xad*\xed\xc8' \
|
||||
b'\x158\x13\xdf\xffF\x9c\x95\x84'
|
||||
|
||||
new_invoice = FakeAddInvoiceResponse()
|
||||
|
||||
else:
|
||||
stub_invoice = InvoiceStub(network=self.rb_cfg.network, chain=self.rb_cfg.chain)
|
||||
new_invoice = create_invoice(stub_invoice, memo, amt)
|
||||
|
||||
log.info("#{}: {}".format(new_invoice.add_index, new_invoice.payment_request))
|
||||
|
||||
invoice_r_hash_hex_str = convert_r_hash_hex_bytes(new_invoice.r_hash)
|
||||
self.invoice_to_check = invoice_r_hash_hex_str
|
||||
log.info("noting down for checking: {}".format(invoice_r_hash_hex_str))
|
||||
|
||||
return new_invoice
|
||||
|
||||
def get_node_uri(self):
|
||||
if IS_DEV_ENV:
|
||||
return "535f209faaea75427949e3e6c1fc9edafbf751f08706506bb873fdc93ffc2d4e2c@pqcjuc47eqcv6mk2.onion:9735"
|
||||
|
||||
stub_readonly = ReadOnlyStub(network=self.rb_cfg.network, chain=self.rb_cfg.chain)
|
||||
|
||||
res = get_node_uri(stub_readonly)
|
||||
log.info("Node URI: : {}".format(res))
|
||||
|
||||
return res
|
||||
|
||||
|
||||
class ClockStoppableThread(QThread):
|
||||
signal = pyqtSignal('PyQt_PyObject', 'PyQt_PyObject')
|
||||
|
||||
def __init__(self, event, interval=0.5, *args, **kwargs):
|
||||
QThread.__init__(self, *args, **kwargs)
|
||||
|
||||
self.stopped = event
|
||||
self.interval = interval
|
||||
# atomic (?!) counter
|
||||
self.ctr = itertools.count()
|
||||
|
||||
def run(self):
|
||||
log.info("starting stoppable clock")
|
||||
while not self.stopped.wait(self.interval):
|
||||
self.signal.emit(self.stopped, next(self.ctr))
|
||||
|
||||
|
||||
class GenerateQrCodeThread(QThread):
|
||||
signal = pyqtSignal('PyQt_PyObject')
|
||||
|
||||
def __init__(self):
|
||||
QThread.__init__(self)
|
||||
self.data = None
|
||||
|
||||
def run(self):
|
||||
# run method gets called when we start the thread
|
||||
img = get_qr_img(self.data)
|
||||
# done, now inform the main thread with the output
|
||||
self.signal.emit(img)
|
||||
|
||||
|
||||
class BeatThread(QThread):
|
||||
signal = pyqtSignal('PyQt_PyObject')
|
||||
|
||||
def __init__(self, interval=5000, *args, **kwargs):
|
||||
QThread.__init__(self, *args, **kwargs)
|
||||
|
||||
self.interval = interval
|
||||
|
||||
self.beat_timer = QTimer()
|
||||
self.beat_timer.moveToThread(self)
|
||||
self.beat_timer.timeout.connect(self.tick)
|
||||
|
||||
def tick(self):
|
||||
# log.debug("beat")
|
||||
self.signal.emit(0)
|
||||
|
||||
def run(self):
|
||||
log.info("starting beat")
|
||||
self.beat_timer.start(self.interval)
|
||||
loop = QEventLoop()
|
||||
loop.exec_()
|
||||
|
||||
|
||||
@lru_cache(maxsize=32)
|
||||
def get_qr_img(data):
|
||||
for i in range(6, 1, -1):
|
||||
time.sleep(1.0)
|
||||
qr_img = qrcode.make(data, box_size=i)
|
||||
log.info("Box Size: {}, Image Size: {}".format(i, qr_img.size[0]))
|
||||
if qr_img.size[0] <= SCREEN_HEIGHT:
|
||||
break
|
||||
else:
|
||||
raise Exception("none found")
|
||||
return qr_img
|
||||
|
||||
|
||||
def main():
|
||||
# make sure CTRL+C works
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
|
||||
description = """BlitzTUI - the Touch-User-Interface for the RaspiBlitz project
|
||||
|
||||
Keep on stacking SATs..! :-D"""
|
||||
|
||||
parser = argparse.ArgumentParser(description=description, formatter_class=RawTextHelpFormatter)
|
||||
parser.add_argument("-V", "--version",
|
||||
help="print version", action="version",
|
||||
version=__version__)
|
||||
#
|
||||
# parser.add_argument("-g", "--game",
|
||||
# help="game binary", type=str)
|
||||
#
|
||||
# parser.add_argument("-s", "--skip",
|
||||
# help="skip", action="store_true")
|
||||
|
||||
# parse args
|
||||
args = parser.parse_args()
|
||||
|
||||
# initialize app
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
w = AppWindow()
|
||||
w.show()
|
||||
|
||||
# run app
|
||||
sys.exit(app.exec_())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
3974
home.admin/BlitzTUI/blitztui/memo.py
Normal file
0
home.admin/BlitzTUI/blitztui/ui/__init__.py
Normal file
417
home.admin/BlitzTUI/blitztui/ui/home.py
Normal file
@ -0,0 +1,417 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'designer/home.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.11.3
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
MainWindow.setObjectName("MainWindow")
|
||||
MainWindow.resize(480, 300)
|
||||
MainWindow.setMinimumSize(QtCore.QSize(0, 0))
|
||||
MainWindow.setAutoFillBackground(False)
|
||||
MainWindow.setStyleSheet("background-color: black")
|
||||
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
||||
self.centralwidget.setObjectName("centralwidget")
|
||||
self.splitter = QtWidgets.QSplitter(self.centralwidget)
|
||||
self.splitter.setGeometry(QtCore.QRect(6, 5, 80, 280))
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.splitter.sizePolicy().hasHeightForWidth())
|
||||
self.splitter.setSizePolicy(sizePolicy)
|
||||
self.splitter.setOrientation(QtCore.Qt.Vertical)
|
||||
self.splitter.setObjectName("splitter")
|
||||
self.pushButton_1 = QtWidgets.QPushButton(self.splitter)
|
||||
palette = QtGui.QPalette()
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Button, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.ButtonText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Button, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.ButtonText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Button, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ButtonText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
|
||||
self.pushButton_1.setPalette(palette)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.pushButton_1.setFont(font)
|
||||
self.pushButton_1.setStyleSheet("background-color: rgb(0, 0, 70);\n"
|
||||
"color: rgb(255, 255, 255)")
|
||||
self.pushButton_1.setObjectName("pushButton_1")
|
||||
self.pushButton_2 = QtWidgets.QPushButton(self.splitter)
|
||||
palette = QtGui.QPalette()
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Button, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.ButtonText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Button, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.ButtonText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Button, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ButtonText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
|
||||
self.pushButton_2.setPalette(palette)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.pushButton_2.setFont(font)
|
||||
self.pushButton_2.setStyleSheet("background-color: rgb(0, 0, 70);\n"
|
||||
"color: rgb(255, 255, 255)")
|
||||
self.pushButton_2.setObjectName("pushButton_2")
|
||||
self.pushButton_3 = QtWidgets.QPushButton(self.splitter)
|
||||
palette = QtGui.QPalette()
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Button, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.ButtonText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Button, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.ButtonText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Button, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ButtonText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
|
||||
self.pushButton_3.setPalette(palette)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setBold(True)
|
||||
font.setUnderline(False)
|
||||
font.setWeight(75)
|
||||
self.pushButton_3.setFont(font)
|
||||
self.pushButton_3.setStyleSheet("background-color: rgb(0, 0, 70);\n"
|
||||
"color: rgb(255, 255, 255)")
|
||||
self.pushButton_3.setObjectName("pushButton_3")
|
||||
self.pushButton_4 = QtWidgets.QPushButton(self.splitter)
|
||||
palette = QtGui.QPalette()
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Button, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.ButtonText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Button, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.ButtonText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Button, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ButtonText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 70))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
|
||||
self.pushButton_4.setPalette(palette)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.pushButton_4.setFont(font)
|
||||
self.pushButton_4.setStyleSheet("background-color: rgb(0, 0, 70);\n"
|
||||
"color: rgb(255, 255, 255)")
|
||||
self.pushButton_4.setObjectName("pushButton_4")
|
||||
self.widget = QtWidgets.QWidget(self.centralwidget)
|
||||
self.widget.setGeometry(QtCore.QRect(92, 5, 380, 270))
|
||||
self.widget.setStyleSheet("background-color: darkblue")
|
||||
self.widget.setObjectName("widget")
|
||||
self.error_label = QtWidgets.QLabel(self.centralwidget)
|
||||
self.error_label.setGeometry(QtCore.QRect(112, 252, 301, 44))
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.error_label.sizePolicy().hasHeightForWidth())
|
||||
self.error_label.setSizePolicy(sizePolicy)
|
||||
palette = QtGui.QPalette()
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 0, 127))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Button, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 0, 127))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 0, 127))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.ButtonText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 0, 127))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Button, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 0, 127))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 0, 127))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.ButtonText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 0, 127))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Button, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 0, 127))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(255, 0, 127))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ButtonText, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
|
||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
|
||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
|
||||
self.error_label.setPalette(palette)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setItalic(False)
|
||||
font.setWeight(50)
|
||||
self.error_label.setFont(font)
|
||||
self.error_label.setStyleSheet("background-color: rgb(0, 0, 0);\n"
|
||||
"font: 12pt \"Arial\";\n"
|
||||
"color: rgb(255, 0, 127);")
|
||||
self.error_label.setScaledContents(False)
|
||||
self.error_label.setAlignment(QtCore.Qt.AlignCenter)
|
||||
self.error_label.setWordWrap(False)
|
||||
self.error_label.setObjectName("error_label")
|
||||
self.buttonBox_close = QtWidgets.QDialogButtonBox(self.centralwidget)
|
||||
self.buttonBox_close.setGeometry(QtCore.QRect(420, 260, 56, 32))
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.buttonBox_close.sizePolicy().hasHeightForWidth())
|
||||
self.buttonBox_close.setSizePolicy(sizePolicy)
|
||||
self.buttonBox_close.setMinimumSize(QtCore.QSize(0, 0))
|
||||
self.buttonBox_close.setMaximumSize(QtCore.QSize(16777215, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setPointSize(14)
|
||||
font.setBold(False)
|
||||
font.setItalic(False)
|
||||
font.setWeight(50)
|
||||
self.buttonBox_close.setFont(font)
|
||||
self.buttonBox_close.setStyleSheet("background-color: lightgrey;\n"
|
||||
"font: 14pt \"Arial\";")
|
||||
self.buttonBox_close.setOrientation(QtCore.Qt.Vertical)
|
||||
self.buttonBox_close.setStandardButtons(QtWidgets.QDialogButtonBox.Close)
|
||||
self.buttonBox_close.setObjectName("buttonBox_close")
|
||||
MainWindow.setCentralWidget(self.centralwidget)
|
||||
|
||||
self.retranslateUi(MainWindow)
|
||||
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||
|
||||
def retranslateUi(self, MainWindow):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
MainWindow.setWindowTitle(_translate("MainWindow", "RaspiBlitz"))
|
||||
self.pushButton_1.setText(_translate("MainWindow", "Info"))
|
||||
self.pushButton_2.setText(_translate("MainWindow", "Node"))
|
||||
self.pushButton_3.setText(_translate("MainWindow", "Invoice"))
|
||||
self.pushButton_4.setText(_translate("MainWindow", "Off"))
|
||||
self.error_label.setText(_translate("MainWindow", "Error Text\n"
|
||||
"Foobar"))
|
||||
|
||||
from . import resources_rc
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
MainWindow = QtWidgets.QMainWindow()
|
||||
ui = Ui_MainWindow()
|
||||
ui.setupUi(MainWindow)
|
||||
MainWindow.show()
|
||||
sys.exit(app.exec_())
|
||||
|
79
home.admin/BlitzTUI/blitztui/ui/invoice.py
Normal file
@ -0,0 +1,79 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'designer/invoice.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.11.3
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_DialogSelectInvoice(object):
|
||||
def setupUi(self, DialogSelectInvoice):
|
||||
DialogSelectInvoice.setObjectName("DialogSelectInvoice")
|
||||
DialogSelectInvoice.resize(480, 320)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(DialogSelectInvoice.sizePolicy().hasHeightForWidth())
|
||||
DialogSelectInvoice.setSizePolicy(sizePolicy)
|
||||
DialogSelectInvoice.setStyleSheet("")
|
||||
self.buttonBox = QtWidgets.QDialogButtonBox(DialogSelectInvoice)
|
||||
self.buttonBox.setGeometry(QtCore.QRect(102, 110, 320, 340))
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.buttonBox.sizePolicy().hasHeightForWidth())
|
||||
self.buttonBox.setSizePolicy(sizePolicy)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setPointSize(28)
|
||||
font.setBold(False)
|
||||
font.setItalic(False)
|
||||
font.setWeight(50)
|
||||
self.buttonBox.setFont(font)
|
||||
self.buttonBox.setStyleSheet("background-color: lightgrey;\n"
|
||||
"font: 28pt \"Arial\";")
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Vertical)
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Yes)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.label = QtWidgets.QLabel(DialogSelectInvoice)
|
||||
self.label.setGeometry(QtCore.QRect(102, 30, 320, 64))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setPointSize(20)
|
||||
font.setBold(False)
|
||||
font.setItalic(False)
|
||||
font.setWeight(50)
|
||||
self.label.setFont(font)
|
||||
self.label.setStyleSheet("")
|
||||
self.label.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop)
|
||||
self.label.setObjectName("label")
|
||||
self.label_2 = QtWidgets.QLabel(DialogSelectInvoice)
|
||||
self.label_2.setGeometry(QtCore.QRect(0, 0, 47, 318))
|
||||
self.label_2.setText("")
|
||||
self.label_2.setPixmap(QtGui.QPixmap(":/RaspiBlitz/images/RaspiBlitz_Logo_Main_270.png"))
|
||||
self.label_2.setScaledContents(True)
|
||||
self.label_2.setObjectName("label_2")
|
||||
|
||||
self.retranslateUi(DialogSelectInvoice)
|
||||
self.buttonBox.accepted.connect(DialogSelectInvoice.accept)
|
||||
self.buttonBox.rejected.connect(DialogSelectInvoice.reject)
|
||||
QtCore.QMetaObject.connectSlotsByName(DialogSelectInvoice)
|
||||
|
||||
def retranslateUi(self, DialogSelectInvoice):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
DialogSelectInvoice.setWindowTitle(_translate("DialogSelectInvoice", "Dialog"))
|
||||
self.label.setText(_translate("DialogSelectInvoice", "Select Invoice"))
|
||||
|
||||
from . import resources_rc
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
DialogSelectInvoice = QtWidgets.QDialog()
|
||||
ui = Ui_DialogSelectInvoice()
|
||||
ui.setupUi(DialogSelectInvoice)
|
||||
DialogSelectInvoice.show()
|
||||
sys.exit(app.exec_())
|
||||
|
84
home.admin/BlitzTUI/blitztui/ui/off.py
Normal file
@ -0,0 +1,84 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'designer/off.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.11.3
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_DialogConfirmOff(object):
|
||||
def setupUi(self, DialogConfirmOff):
|
||||
DialogConfirmOff.setObjectName("DialogConfirmOff")
|
||||
DialogConfirmOff.resize(480, 320)
|
||||
DialogConfirmOff.setStyleSheet("background-color: rgb(255, 128, 128)")
|
||||
self.label_2 = QtWidgets.QLabel(DialogConfirmOff)
|
||||
self.label_2.setGeometry(QtCore.QRect(9, 9, 16, 16))
|
||||
self.label_2.setMaximumSize(QtCore.QSize(110, 320))
|
||||
self.label_2.setText("")
|
||||
self.label_2.setPixmap(QtGui.QPixmap(":/RaspiBlitz/images/RaspiBlitz_Logo_Main_rotate.png"))
|
||||
self.label_2.setScaledContents(True)
|
||||
self.label_2.setIndent(-4)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.label_3 = QtWidgets.QLabel(DialogConfirmOff)
|
||||
self.label_3.setGeometry(QtCore.QRect(0, 0, 47, 318))
|
||||
self.label_3.setText("")
|
||||
self.label_3.setPixmap(QtGui.QPixmap(":/RaspiBlitz/images/RaspiBlitz_Logo_Main_270.png"))
|
||||
self.label_3.setScaledContents(True)
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.label = QtWidgets.QLabel(DialogConfirmOff)
|
||||
self.label.setGeometry(QtCore.QRect(102, 30, 320, 64))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setPointSize(20)
|
||||
font.setBold(False)
|
||||
font.setItalic(False)
|
||||
font.setWeight(50)
|
||||
self.label.setFont(font)
|
||||
self.label.setStyleSheet("")
|
||||
self.label.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop)
|
||||
self.label.setObjectName("label")
|
||||
self.buttonBox = QtWidgets.QDialogButtonBox(DialogConfirmOff)
|
||||
self.buttonBox.setGeometry(QtCore.QRect(102, 110, 320, 340))
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.buttonBox.sizePolicy().hasHeightForWidth())
|
||||
self.buttonBox.setSizePolicy(sizePolicy)
|
||||
self.buttonBox.setMinimumSize(QtCore.QSize(0, 0))
|
||||
self.buttonBox.setMaximumSize(QtCore.QSize(16777215, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setPointSize(28)
|
||||
font.setBold(False)
|
||||
font.setItalic(False)
|
||||
font.setWeight(50)
|
||||
self.buttonBox.setFont(font)
|
||||
self.buttonBox.setStyleSheet("background-color: lightgrey;\n"
|
||||
"font: 28pt \"Arial\";")
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Vertical)
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Retry|QtWidgets.QDialogButtonBox.Yes)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
|
||||
self.retranslateUi(DialogConfirmOff)
|
||||
self.buttonBox.rejected.connect(DialogConfirmOff.reject)
|
||||
self.buttonBox.accepted.connect(DialogConfirmOff.accept)
|
||||
QtCore.QMetaObject.connectSlotsByName(DialogConfirmOff)
|
||||
|
||||
def retranslateUi(self, DialogConfirmOff):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
DialogConfirmOff.setWindowTitle(_translate("DialogConfirmOff", "Dialog"))
|
||||
self.label.setText(_translate("DialogConfirmOff", "Shutdown RaspiBlitz?"))
|
||||
|
||||
from . import resources_rc
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
DialogConfirmOff = QtWidgets.QDialog()
|
||||
ui = Ui_DialogConfirmOff()
|
||||
ui.setupUi(DialogConfirmOff)
|
||||
DialogConfirmOff.show()
|
||||
sys.exit(app.exec_())
|
||||
|
207
home.admin/BlitzTUI/blitztui/ui/qcode.py
Normal file
@ -0,0 +1,207 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'designer/qcode.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.11.3
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_DialogShowQrCode(object):
|
||||
def setupUi(self, DialogShowQrCode):
|
||||
DialogShowQrCode.setObjectName("DialogShowQrCode")
|
||||
DialogShowQrCode.resize(480, 320)
|
||||
self.buttonBox = QtWidgets.QDialogButtonBox(DialogShowQrCode)
|
||||
self.buttonBox.setGeometry(QtCore.QRect(326, 268, 150, 50))
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.buttonBox.sizePolicy().hasHeightForWidth())
|
||||
self.buttonBox.setSizePolicy(sizePolicy)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setPointSize(24)
|
||||
self.buttonBox.setFont(font)
|
||||
self.buttonBox.setStyleSheet("background-color: lightgrey;\n"
|
||||
"font: 24pt \"Arial\";")
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Vertical)
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.top_right_logo = QtWidgets.QLabel(DialogShowQrCode)
|
||||
self.top_right_logo.setGeometry(QtCore.QRect(430, 2, 40, 60))
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.top_right_logo.sizePolicy().hasHeightForWidth())
|
||||
self.top_right_logo.setSizePolicy(sizePolicy)
|
||||
self.top_right_logo.setText("")
|
||||
self.top_right_logo.setPixmap(QtGui.QPixmap(":/RaspiBlitz/images/RaspiBlitz_Logo_Berry.png"))
|
||||
self.top_right_logo.setScaledContents(True)
|
||||
self.top_right_logo.setAlignment(QtCore.Qt.AlignCenter)
|
||||
self.top_right_logo.setObjectName("top_right_logo")
|
||||
self.frame = QtWidgets.QFrame(DialogShowQrCode)
|
||||
self.frame.setGeometry(QtCore.QRect(0, 0, 320, 320))
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth())
|
||||
self.frame.setSizePolicy(sizePolicy)
|
||||
self.frame.setStyleSheet("background-color: rgb(255, 255, 255);")
|
||||
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
|
||||
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
|
||||
self.frame.setObjectName("frame")
|
||||
self.qcode = QtWidgets.QLabel(self.frame)
|
||||
self.qcode.setGeometry(QtCore.QRect(1, 1, 318, 318))
|
||||
self.qcode.setStyleSheet("background-color: white")
|
||||
self.qcode.setText("")
|
||||
self.qcode.setPixmap(QtGui.QPixmap(":/RaspiBlitz/images/RaspiBlitz_Logo_Stacked.png"))
|
||||
self.qcode.setScaledContents(True)
|
||||
self.qcode.setAlignment(QtCore.Qt.AlignCenter)
|
||||
self.qcode.setObjectName("qcode")
|
||||
self.label = QtWidgets.QLabel(DialogShowQrCode)
|
||||
self.label.setGeometry(QtCore.QRect(330, 4, 88, 60))
|
||||
self.label.setText("")
|
||||
self.label.setPixmap(QtGui.QPixmap(":/RaspiBlitz/images/RaspiBlitz_Logo_Stacked.png"))
|
||||
self.label.setScaledContents(True)
|
||||
self.label.setAlignment(QtCore.Qt.AlignCenter)
|
||||
self.label.setObjectName("label")
|
||||
self.horizontalLayoutWidget = QtWidgets.QWidget(DialogShowQrCode)
|
||||
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(320, 70, 161, 191))
|
||||
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(self.horizontalLayoutWidget)
|
||||
self.verticalLayout.setContentsMargins(6, 0, 6, 0)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.line = QtWidgets.QFrame(self.horizontalLayoutWidget)
|
||||
self.line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||
self.line.setObjectName("line")
|
||||
self.verticalLayout.addWidget(self.line)
|
||||
self.memo_key = QtWidgets.QLabel(self.horizontalLayoutWidget)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setPointSize(11)
|
||||
font.setBold(True)
|
||||
font.setItalic(False)
|
||||
font.setUnderline(False)
|
||||
font.setWeight(75)
|
||||
self.memo_key.setFont(font)
|
||||
self.memo_key.setScaledContents(False)
|
||||
self.memo_key.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
|
||||
self.memo_key.setWordWrap(True)
|
||||
self.memo_key.setObjectName("memo_key")
|
||||
self.verticalLayout.addWidget(self.memo_key)
|
||||
self.memo_value = QtWidgets.QLabel(self.horizontalLayoutWidget)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setPointSize(11)
|
||||
self.memo_value.setFont(font)
|
||||
self.memo_value.setScaledContents(False)
|
||||
self.memo_value.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTop|QtCore.Qt.AlignTrailing)
|
||||
self.memo_value.setWordWrap(True)
|
||||
self.memo_value.setObjectName("memo_value")
|
||||
self.verticalLayout.addWidget(self.memo_value)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.status_key = QtWidgets.QLabel(self.horizontalLayoutWidget)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setPointSize(11)
|
||||
font.setBold(True)
|
||||
font.setUnderline(False)
|
||||
font.setWeight(75)
|
||||
self.status_key.setFont(font)
|
||||
self.status_key.setScaledContents(False)
|
||||
self.status_key.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
|
||||
self.status_key.setWordWrap(True)
|
||||
self.status_key.setObjectName("status_key")
|
||||
self.horizontalLayout.addWidget(self.status_key)
|
||||
self.status_value = QtWidgets.QLabel(self.horizontalLayoutWidget)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setPointSize(11)
|
||||
self.status_value.setFont(font)
|
||||
self.status_value.setScaledContents(False)
|
||||
self.status_value.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTop|QtCore.Qt.AlignTrailing)
|
||||
self.status_value.setWordWrap(True)
|
||||
self.status_value.setObjectName("status_value")
|
||||
self.horizontalLayout.addWidget(self.status_value)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||
self.inv_amt_key = QtWidgets.QLabel(self.horizontalLayoutWidget)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setPointSize(11)
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.inv_amt_key.setFont(font)
|
||||
self.inv_amt_key.setObjectName("inv_amt_key")
|
||||
self.verticalLayout.addWidget(self.inv_amt_key)
|
||||
self.inv_amt_value = QtWidgets.QLabel(self.horizontalLayoutWidget)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setPointSize(11)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
self.inv_amt_value.setFont(font)
|
||||
self.inv_amt_value.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||
self.inv_amt_value.setObjectName("inv_amt_value")
|
||||
self.verticalLayout.addWidget(self.inv_amt_value)
|
||||
self.amt_paid_key = QtWidgets.QLabel(self.horizontalLayoutWidget)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setPointSize(11)
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.amt_paid_key.setFont(font)
|
||||
self.amt_paid_key.setObjectName("amt_paid_key")
|
||||
self.verticalLayout.addWidget(self.amt_paid_key)
|
||||
self.amt_paid_value = QtWidgets.QLabel(self.horizontalLayoutWidget)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Arial")
|
||||
font.setPointSize(11)
|
||||
self.amt_paid_value.setFont(font)
|
||||
self.amt_paid_value.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||
self.amt_paid_value.setObjectName("amt_paid_value")
|
||||
self.verticalLayout.addWidget(self.amt_paid_value)
|
||||
self.spinner = QtWidgets.QWidget(DialogShowQrCode)
|
||||
self.spinner.setGeometry(QtCore.QRect(440, 0, 40, 40))
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.spinner.sizePolicy().hasHeightForWidth())
|
||||
self.spinner.setSizePolicy(sizePolicy)
|
||||
self.spinner.setObjectName("spinner")
|
||||
self.spinner.raise_()
|
||||
self.buttonBox.raise_()
|
||||
self.top_right_logo.raise_()
|
||||
self.frame.raise_()
|
||||
self.label.raise_()
|
||||
self.horizontalLayoutWidget.raise_()
|
||||
|
||||
self.retranslateUi(DialogShowQrCode)
|
||||
self.buttonBox.accepted.connect(DialogShowQrCode.accept)
|
||||
QtCore.QMetaObject.connectSlotsByName(DialogShowQrCode)
|
||||
|
||||
def retranslateUi(self, DialogShowQrCode):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
DialogShowQrCode.setWindowTitle(_translate("DialogShowQrCode", "Dialog"))
|
||||
self.memo_key.setText(_translate("DialogShowQrCode", "Memo"))
|
||||
self.memo_value.setText(_translate("DialogShowQrCode", "RB-Vivid-Badger"))
|
||||
self.status_key.setText(_translate("DialogShowQrCode", "Status"))
|
||||
self.status_value.setText(_translate("DialogShowQrCode", "Open/Paid"))
|
||||
self.inv_amt_key.setText(_translate("DialogShowQrCode", "Invoice Amount"))
|
||||
self.inv_amt_value.setText(_translate("DialogShowQrCode", "123456798"))
|
||||
self.amt_paid_key.setText(_translate("DialogShowQrCode", "Amount Paid"))
|
||||
self.amt_paid_value.setText(_translate("DialogShowQrCode", "N/A"))
|
||||
|
||||
from . import resources_rc
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
DialogShowQrCode = QtWidgets.QDialog()
|
||||
ui = Ui_DialogShowQrCode()
|
||||
ui.setupUi(DialogShowQrCode)
|
||||
DialogShowQrCode.show()
|
||||
sys.exit(app.exec_())
|
||||
|
27597
home.admin/BlitzTUI/blitztui/ui/resources_rc.py
Normal file
8
home.admin/BlitzTUI/blitztui/version.py
Normal file
@ -0,0 +1,8 @@
|
||||
""" Store the version here so:
|
||||
# 1) we don't load dependencies by storing it in __init__.py
|
||||
# 2) we can import it in setup.py for the same reason
|
||||
# 3) we can import it into your module module
|
||||
"""
|
||||
|
||||
__version_info__ = ('0', '41', '0')
|
||||
__version__ = '.'.join(__version_info__)
|
2876
home.admin/BlitzTUI/data/Wordlist-Nouns-Common-Audited-Len-3-6.txt
Normal file
3
home.admin/BlitzTUI/data/lnd.conf
Normal file
@ -0,0 +1,3 @@
|
||||
# lnd configuration
|
||||
[Application Options]
|
||||
rpclisten=0.0.0.0:10009
|
19
home.admin/BlitzTUI/data/raspiblitz.conf
Normal file
@ -0,0 +1,19 @@
|
||||
# RASPIBLITZ CONFIG FILE
|
||||
autoNatDiscovery=off
|
||||
autoPilot=off
|
||||
autoUnlock=on
|
||||
chain=test
|
||||
dynDomain=''
|
||||
dynUpdateUrl=''
|
||||
hostname=raspiblitz
|
||||
invoiceAllowDonations=off
|
||||
invoiceDefaultAmount=402
|
||||
lcdrotate=1
|
||||
lndAddress=''
|
||||
lndPort='9735'
|
||||
network=bitcoin
|
||||
publicIP='1.2.3.4'
|
||||
raspiBlitzVersion='1.3'
|
||||
rtlWebinterface=off
|
||||
runBehindTor=off
|
||||
touchscreen=1
|
7
home.admin/BlitzTUI/data/raspiblitz.info
Normal file
@ -0,0 +1,7 @@
|
||||
state=stresstest
|
||||
message='Testing Hardware 60s'
|
||||
network=bitcoin
|
||||
chain=main
|
||||
setupStep=100
|
||||
baseimage=raspbian
|
||||
undervoltageReports=0
|
1082
home.admin/BlitzTUI/designer/home.ui
Normal file
146
home.admin/BlitzTUI/designer/invoice.ui
Normal file
@ -0,0 +1,146 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DialogSelectInvoice</class>
|
||||
<widget class="QDialog" name="DialogSelectInvoice">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>480</width>
|
||||
<height>320</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>102</x>
|
||||
<y>110</y>
|
||||
<width>320</width>
|
||||
<height>340</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>28</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: lightgrey;
|
||||
font: 28pt "Arial";</string>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Yes</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>102</x>
|
||||
<y>30</y>
|
||||
<width>320</width>
|
||||
<height>64</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select Invoice</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>47</width>
|
||||
<height>318</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../resources.qrc">:/RaspiBlitz/images/RaspiBlitz_Logo_Main_270.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../resources.qrc"/>
|
||||
<include location="../resources.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>DialogSelectInvoice</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DialogSelectInvoice</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
180
home.admin/BlitzTUI/designer/off.ui
Normal file
@ -0,0 +1,180 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DialogConfirmOff</class>
|
||||
<widget class="QDialog" name="DialogConfirmOff">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>480</width>
|
||||
<height>320</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(255, 128, 128)</string>
|
||||
</property>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>9</x>
|
||||
<y>9</y>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>110</width>
|
||||
<height>320</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap>:/RaspiBlitz/images/RaspiBlitz_Logo_Main_rotate.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="indent">
|
||||
<number>-4</number>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>47</width>
|
||||
<height>318</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../resources.qrc">:/RaspiBlitz/images/RaspiBlitz_Logo_Main_270.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>102</x>
|
||||
<y>30</y>
|
||||
<width>320</width>
|
||||
<height>64</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Shutdown RaspiBlitz?</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>102</x>
|
||||
<y>110</y>
|
||||
<width>320</width>
|
||||
<height>340</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>28</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: lightgrey;
|
||||
font: 28pt "Arial";</string>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Retry|QDialogButtonBox::Yes</set>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../resources.qrc"/>
|
||||
<include location="../resources.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DialogConfirmOff</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>DialogConfirmOff</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
384
home.admin/BlitzTUI/designer/qcode.ui
Normal file
@ -0,0 +1,384 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DialogShowQrCode</class>
|
||||
<widget class="QDialog" name="DialogShowQrCode">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>480</width>
|
||||
<height>320</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>326</x>
|
||||
<y>268</y>
|
||||
<width>150</width>
|
||||
<height>50</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>24</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: lightgrey;
|
||||
font: 24pt "Arial";</string>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="top_right_logo">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>430</x>
|
||||
<y>2</y>
|
||||
<width>40</width>
|
||||
<height>60</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../resources.qrc">:/RaspiBlitz/images/RaspiBlitz_Logo_Berry.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>320</width>
|
||||
<height>320</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(255, 255, 255);</string>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<widget class="QLabel" name="qcode">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>1</x>
|
||||
<y>1</y>
|
||||
<width>318</width>
|
||||
<height>318</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: white</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../resources.qrc">:/RaspiBlitz/images/RaspiBlitz_Logo_Stacked.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>16</number>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>330</x>
|
||||
<y>4</y>
|
||||
<width>88</width>
|
||||
<height>60</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../resources.qrc">:/RaspiBlitz/images/RaspiBlitz_Logo_Stacked.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>320</x>
|
||||
<y>70</y>
|
||||
<width>161</width>
|
||||
<height>191</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="memo_key">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>11</pointsize>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
<underline>false</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Memo</string>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="memo_value">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>RB-Vivid-Badger</string>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="status_key">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>11</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
<underline>false</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Status</string>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="status_value">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open/Paid</string>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="inv_amt_key">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>11</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Invoice Amount</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="inv_amt_value">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>11</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>123456798</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="amt_paid_key">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>11</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Amount Paid</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="amt_paid_value">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="spinner" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>440</x>
|
||||
<y>0</y>
|
||||
<width>40</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
<zorder>spinner</zorder>
|
||||
<zorder>buttonBox</zorder>
|
||||
<zorder>top_right_logo</zorder>
|
||||
<zorder>frame</zorder>
|
||||
<zorder>label</zorder>
|
||||
<zorder>horizontalLayoutWidget</zorder>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../resources.qrc"/>
|
||||
<include location="../resources.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>DialogShowQrCode</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
166
home.admin/BlitzTUI/docs/README.md
Normal file
@ -0,0 +1,166 @@
|
||||
# BlitzTUI Documentation (mainly for developers)
|
||||
|
||||
BlitzTUI is a part of the RaspiBlitz project and implements a Touch User Interface in PyQt5.
|
||||
|
||||
Make sure that PyQt5 is installed on the system
|
||||
|
||||
```
|
||||
apt-get install python3-pyqt5
|
||||
```
|
||||
|
||||
|
||||
## Required tools
|
||||
|
||||
### for UI development
|
||||
|
||||
* QT Designer (GUI application for Linux, Mac and Windows)
|
||||
|
||||
### for compiling the .ui and .qrc files to python3
|
||||
|
||||
* pyuic5
|
||||
* pyrcc5
|
||||
|
||||
`sudo apt-get install pyqt5-dev-tools`
|
||||
|
||||
### for building and uploading PyPI packages
|
||||
|
||||
* setuptools
|
||||
* wheel
|
||||
* twine
|
||||
|
||||
`python3 -m pip install --upgrade setuptools wheel twine`
|
||||
|
||||
|
||||
## Mini-Tutorial
|
||||
|
||||
Have a look at the [Mini-Tutorial](tutorial.md)
|
||||
|
||||
|
||||
## Release workflow
|
||||
|
||||
* `make build-ui` - in case there were any changes to the *.ui or *.qrc files
|
||||
* make sure you have all changes added and commited (consider re-basing)
|
||||
* update the version in `blitztui/version.py`
|
||||
* update the `CHANGELOG.md` file (reflect the new version!)
|
||||
* `git add CHANGELOG.md blitztui/version.py`
|
||||
* `git commit` and set a proper commit message
|
||||
* `make build`
|
||||
* `make upload`
|
||||
|
||||
|
||||
## Uploading to PyPI
|
||||
|
||||
Please use `twine` for uploading files to PyPI. You will need credentials for the BlitzTUI account.
|
||||
|
||||
```
|
||||
$ cat ~/.pypirc
|
||||
[distutils]
|
||||
index-servers=
|
||||
pypi
|
||||
pypitest
|
||||
|
||||
[pypi]
|
||||
username = RaspiBlitz
|
||||
password = <REDACTED>
|
||||
|
||||
[pypitest]
|
||||
repository = https://test.pypi.org/legacy/
|
||||
username = RaspiBlitz-Test
|
||||
password = <REDACTED>
|
||||
```
|
||||
|
||||
## PRELOAD-What?!
|
||||
|
||||
**Update: This seems to be fixed since grpcio==1.24.3!**
|
||||
|
||||
What's the reason for this long `LD_PRELOAD` line?!
|
||||
|
||||
Apparently there is an incompatibility with the current version (as of writing this: **grpcio==1.24.1**) of
|
||||
**gRPC** for Python on ARM (Raspberry Pi) that was released by Google. Running without `LD_PRELOAD` gives
|
||||
an error regarding `undefined symbol: __atomic_exchange_8`:
|
||||
|
||||
```
|
||||
(python3-env-lnd) admin@raspiblitz:~/raspiblitz/home.admin/BlitzTUI $ python3
|
||||
Python 3.7.3 (default, Apr 3 2019, 05:39:12)
|
||||
[GCC 8.2.0] on linux
|
||||
Type "help", "copyright", "credits" or "license" for more information.
|
||||
>>> import grpc
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
File "/home/admin/python3-env-lnd/lib/python3.7/site-packages/grpc/__init__.py", line 23, in <module>
|
||||
from grpc._cython import cygrpc as _cygrpc
|
||||
ImportError: /home/admin/python3-env-lnd/lib/python3.7/site-packages/grpc/_cython/cygrpc.cpython-37m-arm-linux-gnueabihf.so: undefined symbol: __atomic_exchange_8
|
||||
```
|
||||
|
||||
It is expected that this is resolved soon-ish.
|
||||
|
||||
|
||||
## Directory tree
|
||||
|
||||
```
|
||||
admin@raspiblitz:~/raspiblitz/home.admin/BlitzTUI $ tree
|
||||
.
|
||||
├── blitztui
|
||||
│ ├── client.py
|
||||
│ ├── config.py
|
||||
│ ├── file_logger.py
|
||||
│ ├── file_watcher.py
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py
|
||||
│ ├── memo.py
|
||||
│ ├── ui
|
||||
│ │ ├── home.py
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── invoice.py
|
||||
│ │ ├── off.py
|
||||
│ │ ├── qcode.py
|
||||
│ │ └── resources_rc.py
|
||||
│ └── version.py
|
||||
├── CHANGELOG.md
|
||||
├── data
|
||||
│ ├── lnd.conf
|
||||
│ ├── raspiblitz.conf
|
||||
│ ├── raspiblitz.info
|
||||
│ ├── Wordlist-Adjectives-Common-Audited-Len-3-6.txt
|
||||
│ └── Wordlist-Nouns-Common-Audited-Len-3-6.txt
|
||||
├── designer
|
||||
│ ├── home.ui
|
||||
│ ├── invoice.ui
|
||||
│ ├── off.ui
|
||||
│ └── qcode.ui
|
||||
├── dist
|
||||
├── docs
|
||||
│ ├── images
|
||||
│ │ └── QtDesigner.png
|
||||
│ ├── README.md
|
||||
│ └── tutorial.md
|
||||
├── images
|
||||
│ ├── blank_318x318.png
|
||||
│ ├── Paid_Stamp.png
|
||||
│ ├── RaspiBlitz_Logo_Berry.png
|
||||
│ ├── RaspiBlitz_Logo_Condensed_270.png
|
||||
│ ├── RaspiBlitz_Logo_Condensed_90.png
|
||||
│ ├── RaspiBlitz_Logo_Condensed_Negative.png
|
||||
│ ├── RaspiBlitz_Logo_Condensed.png
|
||||
│ ├── RaspiBlitz_Logo_Icon_Negative.png
|
||||
│ ├── RaspiBlitz_Logo_Icon.png
|
||||
│ ├── RaspiBlitz_Logo_Main_270.png
|
||||
│ ├── RaspiBlitz_Logo_Main_90.png
|
||||
│ ├── RaspiBlitz_Logo_Main_Negative.png
|
||||
│ ├── RaspiBlitz_Logo_Main.png
|
||||
│ ├── RaspiBlitz_Logo_Stacked_270.png
|
||||
│ ├── RaspiBlitz_Logo_Stacked_90.png
|
||||
│ ├── RaspiBlitz_Logo_Stacked_Negative_270.png
|
||||
│ ├── RaspiBlitz_Logo_Stacked_Negative_90.png
|
||||
│ ├── RaspiBlitz_Logo_Stacked_Negative.png
|
||||
│ └── RaspiBlitz_Logo_Stacked.png
|
||||
├── LICENSE
|
||||
├── make.cmd
|
||||
├── Makefile
|
||||
├── MANIFEST.in
|
||||
├── README.md
|
||||
├── requirements.txt
|
||||
├── resources.qrc
|
||||
├── setup.cfg
|
||||
└── setup.py
|
||||
```
|
BIN
home.admin/BlitzTUI/docs/images/QtDesigner.png
Normal file
After Width: | Height: | Size: 84 KiB |
47
home.admin/BlitzTUI/docs/tutorial.md
Normal file
@ -0,0 +1,47 @@
|
||||
# BlitzTUI Mini-Tutorial
|
||||
|
||||
This *Mini-Tutorial* shows the basic workflow for doing changes to the Blitz-Touch-User-Interface.
|
||||
|
||||
## What you need
|
||||
|
||||
* A physical RaspiBlitz and SSH access to it (to verify your changes on the real screen)
|
||||
* A Computer (Mac and Windows should work)
|
||||
* The "Qt Designer" software (https://build-system.fman.io/qt-designer-download)
|
||||
* A copy of the current RaspiBlitz codebase (`git clone https://github.com/rootzoll/raspiblitz.git`)
|
||||
|
||||
## Scenario
|
||||
|
||||
Let's assume you want to reduce the width of the button row on the left side.
|
||||
|
||||
* Open Qt Designer
|
||||
* Load the .ui file: `home.admin/BlitzTUI/designer/home.ui`
|
||||
|
||||
Your screen should look similar to this:
|
||||
|
||||
![Qt Designer](images/QtDesigner.png)
|
||||
|
||||
* (1) for this scenario go to the **Object Inspector** and select **splitter**
|
||||
* (2) change the **Width** (e.g. from 80 to 60)
|
||||
* (3) this should be reflected in the preview Window
|
||||
* (4) save your changes
|
||||
|
||||
The next step is to transfer (use scp or WinSCP) the updated `home.ui` to the RaspiBlitz.
|
||||
|
||||
Login to your RaspiBlitz as **admin** (Password A) and change the directory to `~/raspiblitz/home.admin/BlitzTUI`.
|
||||
|
||||
Your updated `home.ui` file should be in `designer/` (confirm timestamp with `ls -l designer/home.ui`).
|
||||
|
||||
Run `make build-ui`
|
||||
|
||||
To quickly check the result run
|
||||
|
||||
```
|
||||
sudo -u pi DISPLAY=:0.0 LD_PRELOAD=/usr/lib/arm-linux-gnueabihf/libatomic.so.1.2.0 /home/admin/python3-env-lnd/bin/python3 /home/admin/raspiblitz/home.admin/BlitzTUI/blitztui/main.py
|
||||
```
|
||||
|
||||
You can also install the current directory as a python package using `pip install -e .` and the run
|
||||
|
||||
```
|
||||
sudo -u pi DISPLAY=:0.0 LD_PRELOAD=/usr/lib/arm-linux-gnueabihf/libatomic.so.1.2.0 /home/admin/python3-env-lnd/bin/blitz-tui
|
||||
```
|
||||
|
BIN
home.admin/BlitzTUI/images/Paid_Stamp.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
home.admin/BlitzTUI/images/RaspiBlitz_Logo_Berry.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
home.admin/BlitzTUI/images/RaspiBlitz_Logo_Condensed.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
home.admin/BlitzTUI/images/RaspiBlitz_Logo_Condensed_270.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
home.admin/BlitzTUI/images/RaspiBlitz_Logo_Condensed_90.png
Normal file
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 14 KiB |
BIN
home.admin/BlitzTUI/images/RaspiBlitz_Logo_Icon.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
home.admin/BlitzTUI/images/RaspiBlitz_Logo_Icon_Negative.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
home.admin/BlitzTUI/images/RaspiBlitz_Logo_Main.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
home.admin/BlitzTUI/images/RaspiBlitz_Logo_Main_270.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
home.admin/BlitzTUI/images/RaspiBlitz_Logo_Main_90.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
home.admin/BlitzTUI/images/RaspiBlitz_Logo_Main_Negative.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
home.admin/BlitzTUI/images/RaspiBlitz_Logo_Stacked.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
home.admin/BlitzTUI/images/RaspiBlitz_Logo_Stacked_270.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
home.admin/BlitzTUI/images/RaspiBlitz_Logo_Stacked_90.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
home.admin/BlitzTUI/images/RaspiBlitz_Logo_Stacked_Negative.png
Normal file
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 30 KiB |
BIN
home.admin/BlitzTUI/images/blank_318x318.png
Normal file
After Width: | Height: | Size: 1005 B |
10
home.admin/BlitzTUI/make.cmd
Normal file
@ -0,0 +1,10 @@
|
||||
REM run this from BlitzTUI directory
|
||||
|
||||
REM convert ui files to python code
|
||||
pyuic5 -x --import-from "." -o blitztui/ui/qcode.py designer/qcode.ui
|
||||
pyuic5 -x --import-from "." -o blitztui/ui/home.py designer/home.ui
|
||||
pyuic5 -x --import-from "." -o blitztui/ui/off.py designer/off.ui
|
||||
pyuic5 -x --import-from "." -o blitztui/ui/invoice.py designer/invoice.ui
|
||||
|
||||
REM resources
|
||||
pyrcc5 -o blitztui/ui/resources_rc.py resources.qrc
|
6
home.admin/BlitzTUI/requirements.txt
Normal file
@ -0,0 +1,6 @@
|
||||
grpcio>=1.24.3
|
||||
googleapis-common-protos>=1.6.0
|
||||
inotify>=0.2
|
||||
psutil>=5.6
|
||||
pyqtspinner>=0.1
|
||||
qrcode>=6.1
|
23
home.admin/BlitzTUI/resources.qrc
Normal file
@ -0,0 +1,23 @@
|
||||
<RCC>
|
||||
<qresource prefix="RaspiBlitz">
|
||||
<file>images/blank_318x318.png</file>
|
||||
<file>images/Paid_Stamp.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Berry.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Condensed.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Condensed_90.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Condensed_270.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Condensed_Negative.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Icon.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Icon_Negative.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Main.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Main_90.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Main_270.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Main_Negative.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Stacked.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Stacked_90.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Stacked_270.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Stacked_Negative.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Stacked_Negative_90.png</file>
|
||||
<file>images/RaspiBlitz_Logo_Stacked_Negative_270.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
6
home.admin/BlitzTUI/setup.cfg
Normal file
@ -0,0 +1,6 @@
|
||||
# content of setup.cfg
|
||||
[tool:pytest]
|
||||
addopts = -ra -q
|
||||
|
||||
[bdist_wheel]
|
||||
universal = 1
|
39
home.admin/BlitzTUI/setup.py
Normal file
@ -0,0 +1,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import setuptools
|
||||
|
||||
with open("README.md", "r") as fh:
|
||||
long_description = fh.read()
|
||||
|
||||
with open("blitztui/version.py") as f:
|
||||
__version__ = ""
|
||||
exec(f.read()) # set __version__
|
||||
|
||||
setuptools.setup(
|
||||
name="BlitzTUI",
|
||||
version=__version__,
|
||||
author="RaspiBlitz Developers",
|
||||
author_email="raspiblitz@rhab.de",
|
||||
description="Touch User Interface for RaspiBlitz",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
url="https://github.com/rootzoll/raspiblitz",
|
||||
packages=setuptools.find_packages(exclude=("tests", "docs")),
|
||||
classifiers=[
|
||||
# How mature is this project? Common values are
|
||||
# 3 - Alpha
|
||||
# 4 - Beta
|
||||
# 5 - Production/Stable
|
||||
"Development Status :: 4 - Beta",
|
||||
|
||||
"Programming Language :: Python :: 3",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
],
|
||||
python_requires='>=3.4',
|
||||
install_requires=[
|
||||
"grpcio", "googleapis-common-protos", "inotify", "psutil", "pyqtspinner", "qrcode",
|
||||
],
|
||||
entry_points={
|
||||
'console_scripts': ['blitz-tui=blitztui.main:main'],
|
||||
},
|
||||
)
|
@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo ""
|
||||
echo "Thanks"
|
||||
echo "You pressed B2"
|
||||
echo "-----------------------------------------------"
|
||||
echo "Sleep for 10"
|
||||
sleep 10
|
||||
echo "Goodbye"
|
||||
echo "-----------------------------------------------"
|
||||
exit 0
|
@ -70,4 +70,4 @@ sudo -u admin chmod +x /home/admin/config.scripts/*.py
|
||||
echo "******************************************"
|
||||
echo "OK - shell scripts and assests are synced"
|
||||
echo "Reboot recommended"
|
||||
echo ""
|
||||
echo ""
|
||||
|
@ -15,10 +15,6 @@ if [ $# -eq 0 ] || [ "$1" = "-h" ] || [ "$1" = "-help" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# update install sources
|
||||
echo "make sure dependencies are installed ..."
|
||||
sudo apt-get install -y unclutter xterm
|
||||
echo ""
|
||||
|
||||
###################
|
||||
# SWITCH ON
|
||||
@ -28,13 +24,37 @@ if [ "$1" = "1" ] || [ "$1" = "on" ]; then
|
||||
|
||||
echo "Turn ON: Touchscreen"
|
||||
|
||||
# update install sources
|
||||
echo "make sure dependencies are installed ..."
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y unclutter xterm
|
||||
# TODO(frennkie) should this be removed when running "off"?
|
||||
sudo apt-get install -y python3-pyqt5
|
||||
echo ""
|
||||
|
||||
echo "installing BlitzTUI (including dependencies)"
|
||||
/home/admin/python3-env-lnd/bin/pip install BlitzTUI
|
||||
echo ""
|
||||
|
||||
# patch lndlibs for Python3
|
||||
if ! grep -Fxq "from __future__ import absolute_import" /home/admin/config.scripts/lndlibs/rpc_pb2_grpc.py; then
|
||||
sed -i -E '1 a from __future__ import absolute_import' /home/admin/config.scripts/lndlibs/rpc_pb2_grpc.py
|
||||
fi
|
||||
|
||||
if ! grep -Eq "^from . import.*" /home/admin/config.scripts/lndlibs/rpc_pb2_grpc.py; then
|
||||
sed -i -E 's/^(import.*_pb2)/from . \1/' /home/admin/config.scripts/lndlibs/rpc_pb2_grpc.py
|
||||
fi
|
||||
|
||||
# switch to desktop login
|
||||
sudo raspi-config nonint do_boot_behaviour B4
|
||||
|
||||
# set user pi user for autostart
|
||||
sudo sed -i "s/^autologin-user=.*/autologin-user=pi/g" /etc/lightdm/lightdm.conf
|
||||
sudo sed -i s'/--autologin root/--autologin pi/' /etc/systemd/system/getty@tty1.service.d/autologin.conf
|
||||
sudo sed -i s'/--autologin admin/--autologin pi/' /etc/systemd/system/getty@tty1.service.d/autologin.conf
|
||||
sudo sed -i 's/^autologin-user=.*/autologin-user=pi/g' /etc/lightdm/lightdm.conf
|
||||
sudo sed -i 's/--autologin root/--autologin pi/' /etc/systemd/system/getty@tty1.service.d/autologin.conf
|
||||
sudo sed -i 's/--autologin admin/--autologin pi/' /etc/systemd/system/getty@tty1.service.d/autologin.conf
|
||||
|
||||
# remove welcome wizard
|
||||
sudo rm -rf /etc/xdg/autostart/piwiz.desktop
|
||||
|
||||
# write new LXDE autostart config
|
||||
sudo mv /etc/xdg/lxsession/LXDE-pi/autostart /etc/xdg/lxsession/LXDE-pi/autostart.bak
|
||||
@ -49,8 +69,9 @@ EOF
|
||||
# editing autostart.sh
|
||||
cat << EOF | sudo tee /home/pi/autostart.sh >/dev/null
|
||||
#!/bin/sh
|
||||
sleep 1
|
||||
/usr/bin/python3 /home/admin/00infoLCDTK.py
|
||||
|
||||
unset QT_QPA_PLATFORMTHEME
|
||||
/home/admin/python3-env-lnd/bin/blitz-tui
|
||||
EOF
|
||||
sudo chmod a+x /home/pi/autostart.sh
|
||||
sudo chown pi:pi /home/pi/autostart.sh
|
||||
@ -58,6 +79,24 @@ EOF
|
||||
# Remove 00infoLCD.sh from .bashrc of pi user
|
||||
sudo sed -i s'/exec $SCRIPT/#exec $SCRIPT/' /home/pi/.bashrc
|
||||
|
||||
# adapt design by changing openbox settings
|
||||
sudo sed -i -E 's/<weight>Normal</<weight>Bold</g' /etc/xdg/openbox/lxde-pi-rc.xml
|
||||
sudo sed -i -E 's/<name>PibotoLt</<name>Arial</g' /etc/xdg/openbox/lxde-pi-rc.xml
|
||||
sudo sed -i -E 's/window.active.title.bg.color: #87919B/window.active.title.bg.color: #000046/' /usr/share/themes/PiXflat/openbox-3/themerc
|
||||
sudo sed -i -E 's/window.inactive.title.bg.color: #EEEFEE/window.inactive.title.bg.color: #000046/' /usr/share/themes/PiXflat/openbox-3/themerc
|
||||
|
||||
# remove minimize, maximize, close from titlebar
|
||||
sudo sed -i -E 's/titleLayout>LIMC/titleLayout>L/g' /etc/xdg/openbox/lxde-pi-rc.xml
|
||||
|
||||
# Copy over the macaroons
|
||||
sudo mkdir -p /home/pi/.lnd/data/chain/bitcoin/mainnet/
|
||||
sudo chmod 700 /home/pi/.lnd/
|
||||
sudo ln -s /home/admin/.lnd/tls.cert /home/pi/.lnd/
|
||||
sudo cp /home/admin/.lnd/data/chain/bitcoin/mainnet/readonly.macaroon /home/pi/.lnd/data/chain/bitcoin/mainnet/
|
||||
sudo cp /home/admin/.lnd/data/chain/bitcoin/mainnet/invoice.macaroon /home/pi/.lnd/data/chain/bitcoin/mainnet/
|
||||
sudo chmod 600 /home/pi/.lnd/data/chain/bitcoin/mainnet/*.macaroon
|
||||
sudo chown -R pi:pi /home/pi/.lnd/
|
||||
|
||||
# rotate touchscreen based on if LCD is rotated
|
||||
if [ "${lcdrotate}" = "1" ]; then
|
||||
echo "LCD is rotated into default - no touchscreen rotate"
|
||||
@ -100,7 +139,7 @@ if [ "$1" = "0" ] || [ "$1" = "off" ]; then
|
||||
sudo sed -i s'/--autologin admin/--autologin pi/' /etc/systemd/system/getty@tty1.service.d/autologin.conf
|
||||
|
||||
# move back old LXDE autostart config
|
||||
sudp rm /etc/xdg/lxsession/LXDE-pi/autostart
|
||||
sudo rm /etc/xdg/lxsession/LXDE-pi/autostart
|
||||
sudo mv /etc/xdg/lxsession/LXDE-pi/autostart.bak /etc/xdg/lxsession/LXDE-pi/autostart
|
||||
|
||||
# add again 00infoLCD.sh to .bashrc of pi user
|
||||
|