class BitcoindConfigurationTab(QWidget): def __init__(self, bitcoind_node: BitcoindNode): super().__init__() self.bitcoind_node = bitcoind_node self.layout = QGridLayout() self.bitcoin_version = SelectableText( f'Bitcoin Core ' f'version {self.bitcoind_node.software.release_version}' ) self.layout.addWidget(self.bitcoin_version) self.data_directory_group_box = DataDirectoryBox( bitcoin_node=self.bitcoind_node) self.data_directory_group_box.file_dialog.new_data_directory.connect( self.change_datadir ) self.layout.addWidget(self.data_directory_group_box) self.layout.setAlignment(self.data_directory_group_box, Qt.AlignHCenter) self.enable_wallet_label = QLabel('Enable wallet') self.enable_wallet_widget = QCheckBox('Enable Wallet') self.enable_wallet_widget.stateChanged.connect( lambda x: self.set_conf_value('disablewallet', not bool(x)) ) self.layout.addWidget(self.enable_wallet_widget) self.layout.addWidget(HorizontalLine()) self.restart_layout = BitcoindRestartLayout(bitcoin=self.bitcoind_node) self.layout.addLayout(self.restart_layout) self.show_bitcoin_conf = QPushButton('Show bitcoin.conf') self.show_bitcoin_conf.clicked.connect( lambda: reveal(self.bitcoind_node.configuration.file.path) ) self.layout.addWidget(self.show_bitcoin_conf) self.setLayout(self.layout) def change_datadir(self, new_datadir: str): self.bitcoind_node.file['datadir'] = new_datadir self.bitcoind_node.set_prune() self.data_directory_group_box.set_datadir( self.bitcoind_node.file['datadir'], self.bitcoind_node.file['prune'] ) @staticmethod def set_checked(widget: QCheckBox, state: bool): if state is None: widget.setChecked(False) return widget.setChecked(state) def set_conf_value(self, key: str, new_value): self.bitcoind_node.file[key] = new_value
class AdvancedWidget(QWidget): def __init__(self, node_set: NodeSet): super().__init__() self.setWindowTitle('Advanced') self.node_set = node_set self.columns = 2 self.layout = QGridLayout() self.versions_layout = VersionsLayout(node_set=node_set) self.ports_layout = PortsLayout(node_set=node_set) self.actions_layout = ConfigurationFilesLayout(node_set=node_set) self.zap_layout = ZapLayout(node_set=self.node_set) self.tls_layout = TlsLayout(node_set=self.node_set) self.layout.addLayout(self.versions_layout, column_span=self.columns) self.layout.addWidget(HorizontalLine(), column_span=self.columns) self.layout.addLayout(self.ports_layout, column_span=self.columns) self.layout.addWidget(HorizontalLine(), column_span=self.columns) self.layout.addLayout(self.actions_layout, column_span=self.columns) self.layout.addWidget(HorizontalLine(), column_span=self.columns) self.layout.addLayout(self.zap_layout, column_span=self.columns) self.layout.addWidget(HorizontalLine(), column_span=self.columns) self.layout.addLayout(self.tls_layout, column_span=self.columns) self.setLayout(self.layout) def show(self): super().show() self.raise_() self.setWindowState(self.windowState() & ~Qt.WindowMinimized | Qt.WindowActive) self.activateWindow()
class AdvancedWidget(QWidget): def __init__(self, node_set: NodeSet): super().__init__() self.setWindowTitle('Advanced') self.node_set = node_set self.columns = 2 self.layout = QGridLayout() self.versions_layout = VersionsLayout(node_set=node_set) self.ports_layout = PortsLayout(node_set=node_set) self.actions_layout = ConfigurationFilesLayout(node_set=node_set) self.zap_layout = ZapLayout(node_set=self.node_set) self.tls_layout = TlsLayout(node_set=self.node_set) self.layout.addLayout(self.versions_layout, column_span=self.columns) self.layout.addWidget(HorizontalLine(), column_span=self.columns) self.layout.addLayout(self.ports_layout, column_span=self.columns) self.layout.addWidget(HorizontalLine(), column_span=self.columns) self.layout.addLayout(self.actions_layout, column_span=self.columns) self.layout.addWidget(HorizontalLine(), column_span=self.columns) self.layout.addLayout(self.zap_layout, column_span=self.columns) self.layout.addWidget(HorizontalLine(), column_span=self.columns) self.layout.addLayout(self.tls_layout, column_span=self.columns) self.setLayout(self.layout)
class LndConfigurationTab(QWidget): def __init__(self, lnd: Lnd): super().__init__() self.lnd = lnd self.layout = QGridLayout() self.lnd_version = SelectableText( f'LND ' f'version {self.lnd.software.release_version}') self.layout.addWidget(self.lnd_version) self.alias_layout = AliasLayout() color = self.lnd.file['color'] self.alias_layout.set_color(color) self.alias_layout.new_color.connect( lambda x: self.set_conf_value('color', x)) self.alias_layout.alias_editor.textEdited.connect( lambda x: self.set_conf_value('alias', x)) self.layout.addLayout(self.alias_layout) self.layout.addWidget(HorizontalLine()) self.ports_layout = LndPortsLayout(lnd=self.lnd) self.layout.addLayout(self.ports_layout) self.layout.addWidget(HorizontalLine()) self.restart_layout = LndRestartLayout(lnd=self.lnd) self.layout.addLayout(self.restart_layout) self.tls_layout = TlsLayout(lnd=self.lnd) self.layout.addLayout(self.tls_layout) self.show_lnd_conf = QPushButton('Show lnd.conf') self.show_lnd_conf.clicked.connect( lambda: reveal(self.lnd.file.directory)) self.layout.addWidget(self.show_lnd_conf) self.setLayout(self.layout) def set_conf_value(self, key: str, new_value: str): self.lnd.file[key] = new_value def show(self): super().show() self.raise_() self.setWindowState(self.windowState() & ~Qt.WindowMinimized | Qt.WindowActive) self.activateWindow()
class ConsoleDialog(QDialog): def __init__(self, title: str, program: str, args: List[str], commands: List[str]): super().__init__() self.setWindowTitle(title) self.program = program self.args = args self.layout = QGridLayout() self.output = QTextEdit() self.output.acceptRichText = True self.input = QLineEdit() self.completer = QCompleter(commands, self) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.input.setCompleter(self.completer) self.input.setFocus() self.layout.addWidget(self.output) self.layout.addWidget(self.input) self.setLayout(self.layout) self.connect(self.input, SIGNAL("returnPressed(void)"), self.execute_user_command) self.connect(self.completer, SIGNAL("activated(const QString&)"), self.input.clear, Qt.QueuedConnection) def execute_user_command(self): cmd = str(self.input.text()) self.run_command(cmd) def run_command(self, cmd: str): log.info( 'run_command', program=self.program, args=self.args, cmd=cmd ) self.output.append(f'> {cmd}\n') self.input.clear() process = QProcess() process.setProgram(self.program) process.setCurrentReadChannel(0) # noinspection PyUnresolvedReferences process.readyReadStandardError.connect( lambda: self.handle_error(process) ) # noinspection PyUnresolvedReferences process.readyReadStandardOutput.connect( lambda: self.handle_output(process) ) connect_args = list(self.args) args = cmd.split(' ') if args[0] == self.program.split('/')[-1]: args.pop(0) process.setArguments(connect_args + args) process.start() def handle_error(self, process: QProcess): output: QByteArray = process.readAllStandardError() message = output.data().decode('utf-8').strip() self.output.append(message) def handle_output(self, process: QProcess): output: QByteArray = process.readAllStandardOutput() message = output.data().decode('utf-8').strip() if message.startswith('{') or message.startswith('['): formatter = HtmlFormatter() formatter.noclasses = True formatter.linenos = False formatter.nobackground = True message = highlight(message, JsonLexer(), formatter) self.output.insertHtml(message) else: self.output.append(message) # This is just for generating the command lists in constants # commands = None # if '== Blockchain ==' in message: # commands = self.parse_litecoin_cli_commands(message) # elif 'lncli [global options] command [command options]' in message: # commands = self.parse_lncli_commands(message) # if commands is not None: # log.debug('commands', commands=commands) max_scroll = self.output.verticalScrollBar().maximum() self.output.verticalScrollBar().setValue(max_scroll) @staticmethod def parse_litecoin_cli_commands(message: str): log.debug('parse_litecoin_cli_commands') commands = [] for line in message.split(sep='\n'): line = line.strip() if not line or line.startswith('=='): continue command = line.split()[0] command = command.strip() commands.append(command) return commands @staticmethod def parse_lncli_commands(message: str): log.debug('parse_lncli_commands') at_commands = False commands = [] for line in message.split(sep='\n'): line = line.strip() if not at_commands: if 'COMMANDS:' in line: at_commands = True log.debug('commands line', line=line) continue elif 'GLOBAL OPTIONS' in line: return commands elif line.endswith(':') or not line: continue command = line.split()[0] command = command.strip().replace(',', '') commands.append(command) return commands def show(self): self.showMaximized() self.raise_() self.setWindowState(self.windowState() & ~Qt.WindowMinimized | Qt.WindowActive) self.activateWindow() self.input.setFocus() self.run_command('help')