Ejemplo n.º 1
0
class MainWindow12(QMainWindow):
    def __init__(self):
        super(MainWindow12, self).__init__()

        self.commandslist = []
        self.tracker = 0
        os.chdir(os.path.expanduser(path12))
        #        print(os.getcwd())
        self.name = (str(getpass.getuser()) + "@" + str(socket.gethostname()) +
                     ":" + str(os.getcwd()) + "$ ")
        self.setWindowTitle('PyQt5Terminal')
        self.setWindowIcon(QIcon.fromTheme("terminal-emulator"))
        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.MergedChannels)
        self.process.readyRead.connect(self.dataReady)
        self.process.readyReadStandardError.connect(
            self.onReadyReadStandardError)
        self.process.readyReadStandardOutput.connect(
            self.onReadyReadStandardOutput)
        self.process.finished.connect(self.isFinished)
        self.process.setWorkingDirectory(os.getcwd())
        self.createStatusBar()

        self.commandfield = QPlainTextEdit()
        self.commandfield.setLineWrapMode(QPlainTextEdit.NoWrap)
        self.commandfield.setFixedHeight(44)
        self.commandfield.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.commandfield.setAcceptDrops(True)
        self.cursor = self.commandfield.textCursor()

        self.textWindow = QPlainTextEdit(self)
        #self.setStyleSheet(mystylesheet(self))

        self.textWindow.setReadOnly(True)
        layout = QVBoxLayout()
        layout.addWidget(self.textWindow)
        layout.addWidget(self.commandfield)
        self.wid = QWidget()
        self.wid.setLayout(layout)
        self.setCentralWidget(self.wid)
        self.setGeometry(0, 0, 600, 500)
        self.commandfield.setPlainText(self.name)
        self.cursorEnd()
        self.commandfield.setFocus()

        self.copySelectedTextAction = QAction(QIcon.fromTheme("edit-copy"),
                                              "Copy",
                                              shortcut="Shift+Ctrl+c",
                                              triggered=self.copyText)
        self.textWindow.addAction(self.copySelectedTextAction)
        self.pasteTextAction = QAction(QIcon.fromTheme("edit-paste"),
                                       "Copy",
                                       shortcut="Shift+Ctrl+v",
                                       triggered=self.pasteText)
        self.commandfield.addAction(self.pasteTextAction)

        self.cancelAction = QAction("Cancel",
                                    shortcut="Ctrl+c",
                                    triggered=self.killProcess)
        self.textWindow.addAction(self.cancelAction)

        self.commandfield.installEventFilter(self)
        #        self.textWindow.installEventFilter(self)
        QApplication.setCursorFlashTime(1000)
        self.cursorEnd()
        print(self.process.workingDirectory())
        self.settings = QSettings("QTerminal", "QTerminal")
        self.readSettings()

    def closeEvent(self, e):
        self.writeSettings()

    def cursorEnd(self):
        self.name = (str(getpass.getuser()) + "@" + str(socket.gethostname()) +
                     ":" + str(os.getcwd()) + "$ ")
        self.commandfield.setPlainText(self.name)
        cursor = self.commandfield.textCursor()
        cursor.movePosition(11, 0)
        self.commandfield.setTextCursor(cursor)
        self.commandfield.setFocus()

    def eventFilter(self, source, event):
        if source == self.commandfield:
            if (event.type() == QEvent.DragEnter):
                event.accept()
                return True
            elif (event.type() == QEvent.Drop):
                print('Drop')
                self.setDropEvent(event)
                return True
            elif (event.type() == QEvent.KeyPress):
                cursor = self.commandfield.textCursor()
                #                print('key press:', (event.key(), event.text()))
                if event.key() == Qt.Key_Backspace:
                    if cursor.positionInBlock() <= len(self.name):
                        return True
                    else:
                        return False

                elif event.key() == Qt.Key_Return:
                    self.run()
                    return True

                elif event.key() == Qt.Key_Left:
                    if cursor.positionInBlock() <= len(self.name):
                        return True
                    else:
                        return False

                elif event.key() == Qt.Key_Delete:
                    if cursor.positionInBlock() <= len(self.name) - 1:
                        return True
                    else:
                        return False

                elif event.modifiers() == Qt.ControlModifier and event.key(
                ) == Qt.Key_C:
                    self.killProcess()
                    return True

                elif event.key() == Qt.Key_Up:
                    try:
                        if self.tracker != 0:
                            cursor.select(QTextCursor.BlockUnderCursor)
                            cursor.removeSelectedText()
                            self.commandfield.appendPlainText(self.name)

                        self.commandfield.insertPlainText(
                            self.commandslist[self.tracker])
                        self.tracker -= 1

                    except IndexError:
                        self.tracker = 0
                    return True

                elif event.key() == Qt.Key_Down:
                    try:
                        if self.tracker != 0:
                            cursor.select(QTextCursor.BlockUnderCursor)
                            cursor.removeSelectedText()
                            self.commandfield.appendPlainText(self.name)

                        self.commandfield.insertPlainText(
                            self.commandslist[self.tracker])
                        self.tracker += 1

                    except IndexError:
                        self.tracker = 0
                    return True

                else:
                    return False
            else:
                return False
        else:
            return False

    def copyText(self):
        self.textWindow.copy()

    def pasteText(self):
        self.commandfield.paste()

    def killProcess(self):
        print("cancelled")
        self.process.kill()
        self.textWindow.appendPlainText("cancelled")
        self.cursorEnd()

    def createStatusBar(self):
        sysinfo = QSysInfo()
        myMachine = "current CPU Architecture: " + sysinfo.currentCpuArchitecture(
        ) + " *** " + sysinfo.prettyProductName(
        ) + " *** " + sysinfo.kernelType() + " " + sysinfo.kernelVersion()
        self.statusBar().showMessage(myMachine, 0)

    def setDropEvent(self, event):
        self.commandfield.setFocus()
        if event.mimeData().hasUrls():
            f = str(event.mimeData().urls()[0].toLocalFile())
            print("is file:", f)
            if " " in f:
                self.commandfield.insertPlainText("'{}'".format(f))
            else:
                self.commandfield.insertPlainText(f)
            event.accept()
        elif event.mimeData().hasText():
            ft = event.mimeData().text()
            print("is text:", ft)
            if " " in ft:
                self.commandfield.insertPlainText("'{}'".format(ft))
            else:
                self.commandfield.insertPlainText(ft)
        else:
            event.ignore()

    def run(self):
        print("started")
        cli = []
        cmd = ""
        t = ""
        self.textWindow.setFocus()
        self.textWindow.appendPlainText(self.commandfield.toPlainText())
        cli = shlex.split(self.commandfield.toPlainText().replace(
            self.name, '').replace("'", '"'),
                          posix=False)
        cmd = str(cli[0])  ### is the executable

        if cmd == "exit":
            quit()

        elif cmd == "cd":
            del cli[0]
            path = " ".join(cli)
            os.chdir(os.path.abspath(path))
            self.process.setWorkingDirectory(os.getcwd())
            print("workingDirectory:", self.process.workingDirectory())
            self.cursorEnd()
        else:
            self.process.setWorkingDirectory(os.getcwd())
            print("workingDirectory", self.process.workingDirectory())
            del cli[0]
            if (QStandardPaths.findExecutable(cmd)):
                self.commandslist.append(
                    self.commandfield.toPlainText().replace(self.name, ""))
                print("command", cmd, "found")
                t = " ".join(cli)
                if self.process.state() != 2:
                    #self.process.waitForStarted()
                    self.process.waitForReadyRead()
                    self.process.waitForFinished()
                    if "|" in t or ">" in t or "<" in t:
                        print("special characters")
                        self.process.start('sh -c "' + cmd + ' ' + t + '"')
                        print("running", ('sh -c "' + cmd + ' ' + t + '"'))
                    else:
                        self.process.start(cmd + " " + t)
                        print("running", (cmd + " " + t))
            else:
                print("command not found ...")
                self.textWindow.appendPlainText("command not found ...")
                self.cursorEnd()

    def dataReady(self):
        out = ""
        try:
            out = str(self.process.readAll(), encoding='utf8').rstrip()
        except TypeError:
            out = str(self.process.readAll()).rstrip()
            self.textWindow.moveCursor(self.cursor.Start)  ### changed
        self.textWindow.appendPlainText(out)

    def onReadyReadStandardError(self):
        self.error = self.process.readAllStandardError().data().decode()
        self.textWindow.appendPlainText(self.error.strip('\n'))
        self.cursorEnd()

    def onReadyReadStandardOutput(self):
        self.result = self.process.readAllStandardOutput().data().decode()
        self.textWindow.appendPlainText(self.result.strip('\n'))
        self.cursorEnd()
        self.state = self.process.state()

    def isFinished(self):
        print("finished")
        self.name = (str(getpass.getuser()) + "@" + str(socket.gethostname()) +
                     ":" + str(os.getcwd()) + "$ ")
        self.commandfield.setPlainText(self.name)
        self.cursorEnd()

    def readSettings(self):
        if self.settings.contains("commands"):
            self.commandslist = self.settings.value("commands")
        if self.settings.contains("pos"):
            pos = self.settings.value("pos", QPoint(200, 200))
            self.move(pos)
        if self.settings.contains("size"):
            size = self.settings.value("size", QSize(400, 400))
            self.resize(size)

    def writeSettings(self):
        self.settings.setValue("commands", self.commandslist)
        self.settings.setValue("pos", self.pos())
        self.settings.setValue("size", self.size())