--- a/PyInstaller/PyInstallerExecDialog.py Thu May 27 19:23:58 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,196 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2018 - 2021 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Module implementing a dialog to show the output of the pyinstaller/pyi-makespec -process. -""" - -import os - -from PyQt5.QtCore import pyqtSlot, QProcess, QTimer -from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton - -from E5Gui import E5MessageBox - -from .Ui_PyInstallerExecDialog import Ui_PyInstallerExecDialog - -import Preferences - - -class PyInstallerExecDialog(QDialog, Ui_PyInstallerExecDialog): - """ - Class implementing a dialog to show the output of the - pyinstaller/pyi-makespec process. - - This class starts a QProcess and displays a dialog that - shows the output of the packager command process. - """ - def __init__(self, cmdname, parent=None): - """ - Constructor - - @param cmdname name of the packager - @type str - @param parent reference to the parent widget - @type QWidget - """ - super().__init__(parent) - self.setupUi(self) - - self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) - self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) - - self.__process = None - self.__cmdname = cmdname # used for several outputs - - def start(self, args, parms, project, script): - """ - Public slot to start the packager command. - - @param args command line arguments for packager program - @type list of str - @param parms parameters got from the config dialog - @type dict - @param project reference to the project object - @type Project - @param script script or spec file name to be processed by by the - packager - @type str - @return flag indicating the successful start of the process - @rtype bool - """ - self.__project = project - - if not os.path.isabs(script): - # assume relative paths are relative to the project directory - script = os.path.join(self.__project.getProjectPath(), script) - dname = os.path.dirname(script) - self.__script = os.path.basename(script) - - self.contents.clear() - - args.append(self.__script) - - self.__process = QProcess() - self.__process.setWorkingDirectory(dname) - - self.__process.readyReadStandardOutput.connect(self.__readStdout) - self.__process.readyReadStandardError.connect(self.__readStderr) - self.__process.finished.connect(self.__finishedProcess) - - self.setWindowTitle(self.tr('{0} - {1}').format( - self.__cmdname, script)) - self.contents.insertPlainText("{0} {1}\n\n".format( - ' '.join(args), os.path.join(dname, self.__script))) - self.contents.ensureCursorVisible() - - program = args.pop(0) - self.__process.start(program, args) - procStarted = self.__process.waitForStarted() - if not procStarted: - E5MessageBox.critical( - self, - self.tr('Process Generation Error'), - self.tr( - 'The process {0} could not be started. ' - 'Ensure, that it is in the search path.' - ).format(program)) - return procStarted - - @pyqtSlot(QAbstractButton) - def on_buttonBox_clicked(self, button): - """ - Private slot called by a button of the button box clicked. - - @param button button that was clicked - @type QAbstractButton - """ - if button == self.buttonBox.button(QDialogButtonBox.Close): - self.accept() - elif button == self.buttonBox.button(QDialogButtonBox.Cancel): - self.__finish() - - def __finish(self): - """ - Private slot called when the process was canceled by the user. - - It is called when the process finished or - the user pressed the cancel button. - """ - if self.__process is not None: - self.__process.disconnect(self.__finishedProcess) - self.__process.terminate() - QTimer.singleShot(2000, self.__process.kill) - self.__process.waitForFinished(3000) - self.__process = None - - self.contents.insertPlainText( - self.tr('\n{0} aborted.\n').format(self.__cmdname)) - - self.__enableButtons() - - def __finishedProcess(self): - """ - Private slot called when the process finished. - - It is called when the process finished or - the user pressed the cancel button. - """ - if self.__process.exitStatus() == QProcess.NormalExit: - # add the spec file to the project - self.__project.addToOthers( - os.path.splitext(self.__script)[0] + ".spec") - - self.__process = None - - self.contents.insertPlainText( - self.tr('\n{0} finished.\n').format(self.__cmdname)) - - self.__enableButtons() - - def __enableButtons(self): - """ - Private slot called when all processes finished. - - It is called when the process finished or - the user pressed the cancel button. - """ - self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) - self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) - self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) - self.contents.ensureCursorVisible() - - def __readStdout(self): - """ - Private slot to handle the readyReadStandardOutput signal. - - It reads the output of the process, formats it and inserts it into - the contents pane. - """ - self.__process.setReadChannel(QProcess.StandardOutput) - - while self.__process.canReadLine(): - s = str(self.__process.readAllStandardOutput(), - Preferences.getSystem("IOEncoding"), - 'replace') - self.contents.insertPlainText(s) - self.contents.ensureCursorVisible() - - def __readStderr(self): - """ - Private slot to handle the readyReadStandardError signal. - - It reads the error output of the process and inserts it into the - error pane. - """ - self.__process.setReadChannel(QProcess.StandardError) - - while self.__process.canReadLine(): - s = str(self.__process.readAllStandardError(), - Preferences.getSystem("IOEncoding"), - 'replace') - self.contents.insertPlainText(s) - self.contents.ensureCursorVisible()