PyQT terminal emulator
Asked Answered
F

2

7

I am trying to develop a "console" in pyqt. Similar to xterm.js where all the console is, is front end it does not spawn any sub-processes its just an I/O for me to plug in whatever I want to at a later date.

are there any existing python packages or simple widgets I can use that would allow me to put a terminal like interface within my pyqt application?

its a client server application so the terminal is used to send commands to the backend server and retrieve output as if it were a bash shell (for example)

Fortin answered 12/6, 2020 at 17:10 Comment(5)
use QTermWidgetCuba
@Cuba Thanks I am looking into this now; do you have any documentation you could link me? Im having a had time finding a good example ?? qconsole and qtermwidget5-data are installed but no idea how to use themFortin
then you have managed to install qtermwidget, from what I understand is that you want to write a command to the pseudo terminal and when you press enter it is sent to a server, and the server response should be reflected in the terminal, am I correct?Cuba
@Cuba the back end is pty (all done) I just want to transfer my data from pty to the client (already done) and now I have no idea how to even code or call the widget in python so i can display the data in the pyqt because there is no examples or documentation for this widget :( (that I can find)Fortin
See my answer....Cuba
C
3

You can use QTermWidget (if you can't install it and you're using ubuntu then you can check this answer).

For example a translation of the official RemoteTerm example that allows to access the shell remotely through sockets would be the following:

terminal.py

import os
import sys

from PyQt5 import QtCore, QtWidgets, QtNetwork

import QTermWidget


class RemoteTerm(QTermWidget.QTermWidget):
    def __init__(self, ipaddr, port, parent=None):
        super().__init__(0, parent)

        self.socket = QtNetwork.QTcpSocket(self)

        self.socket.error.connect(self.atError)
        self.socket.readyRead.connect(self.on_readyRead)
        self.sendData.connect(self.socket.write)

        self.startTerminalTeletype()
        self.socket.connectToHost(ipaddr, port)

    @QtCore.pyqtSlot()
    def on_readyRead(self):
        data = self.socket.readAll().data()
        os.write(self.getPtySlaveFd(), data)

    @QtCore.pyqtSlot()
    def atError(self):
        print(self.socket.errorString())


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)

    QtCore.QCoreApplication.setApplicationName("QTermWidget Test")
    QtCore.QCoreApplication.setApplicationVersion("1.0")

    parser = QtCore.QCommandLineParser()
    parser.addHelpOption()
    parser.addVersionOption()
    parser.setApplicationDescription(
        "Example(client-side) for remote terminal of QTermWidget"
    )
    parser.addPositionalArgument("ipaddr", "adrress of host")
    parser.addPositionalArgument("port", "port of host")

    parser.process(QtCore.QCoreApplication.arguments())

    requiredArguments = parser.positionalArguments()
    if len(requiredArguments) != 2:
        parser.showHelp(1)
        sys.exit(-1)

    address, port = requiredArguments
    w = RemoteTerm(QtNetwork.QHostAddress(address), int(port))
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())

shell-srv.py

#!/usr/bin/env python

import sys
import os
import socket
import pty


def usage(program):
    print("Example(server-side) for remote terminal of QTermWidget.")
    print("Usage: %s ipaddr port" % program)


def main():
    if len(sys.argv) != 3:
        usage(sys.argv[0])
        sys.exit(1)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        s.bind((sys.argv[1], int(sys.argv[2])))
        s.listen(0)
        print("[+]Start Server.")
    except Exception as e:
        print("[-]Error Happened: %s" % e.message)
        sys.exit(2)

    while True:
        c = s.accept()
        os.dup2(c[0].fileno(), 0)
        os.dup2(c[0].fileno(), 1)
        os.dup2(c[0].fileno(), 2)

        # It's important to use pty to spawn the shell.
        pty.spawn("/bin/sh")
        c[0].close()


if __name__ == "__main__":
    main()
Cuba answered 12/6, 2020 at 22:12 Comment(1)
wooo great something that makes sense to me! nothing says it better than codeFortin
F
0

The qtpyTerminal project provides a terminal widget derived from QPlainTextEdit, which emulates VT100 thanks to Pyte (https://github.com/selectel/pyte).

See https://github.com/mguijarr/qtpyTerminal .

It works with qtpy, so multiple Qt backends are supported.

Factual answered 13/9 at 11:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.