PyInstaller/PyInstallerExecDialog.py

changeset 5
8c92d66d20e4
child 25
3d7e12729e7c
equal deleted inserted replaced
4:52f0572b5908 5:8c92d66d20e4
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2018 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to show the output of the pyinstaller/pyi-makespec
8 process.
9 """
10
11 from __future__ import unicode_literals
12 try:
13 str = unicode
14 except NameError:
15 pass
16
17 import os
18
19 from PyQt5.QtCore import pyqtSlot, QProcess, QTimer
20 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton
21
22 from E5Gui import E5MessageBox
23
24 from .Ui_PyInstallerExecDialog import Ui_PyInstallerExecDialog
25
26 import Preferences
27
28
29 class PyInstallerExecDialog(QDialog, Ui_PyInstallerExecDialog):
30 """
31 Class implementing a dialog to show the output of the
32 pyinstaller/pyi-makespec process.
33
34 This class starts a QProcess and displays a dialog that
35 shows the output of the packager command process.
36 """
37 def __init__(self, cmdname, parent=None):
38 """
39 Constructor
40
41 @param cmdname name of the packager
42 @type str
43 @param parent reference to the parent widget
44 @type QWidget
45 """
46 super(PyInstallerExecDialog, self).__init__(parent)
47 self.setupUi(self)
48
49 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
50 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
51
52 self.__process = None
53 self.__cmdname = cmdname # used for several outputs
54
55 def start(self, args, parms, project, script):
56 """
57 Public slot to start the packager command.
58
59 @param args command line arguments for packager program
60 @type list of str
61 @param parms parameters got from the config dialog
62 @type dict
63 @param project reference to the project object
64 @type Project
65 @param script script or spec file name to be processed by by the
66 packager
67 @type str
68 @return flag indicating the successful start of the process
69 @rtype bool
70 """
71 self.__project = project
72
73 if not os.path.isabs(script):
74 # assume relative paths are relative to the project directory
75 script = os.path.join(self.__project.getProjectPath(), script)
76 dname = os.path.dirname(script)
77 self.__script = os.path.basename(script)
78
79 self.contents.clear()
80
81 args.append(self.__script)
82
83 self.__process = QProcess()
84 self.__process.setWorkingDirectory(dname)
85
86 self.__process.readyReadStandardOutput.connect(self.__readStdout)
87 self.__process.readyReadStandardError.connect(self.__readStderr)
88 self.__process.finished.connect(self.__finishedProcess)
89
90 self.setWindowTitle(self.tr('{0} - {1}').format(
91 self.__cmdname, script))
92 self.contents.insertPlainText("{0} {1}\n\n".format(
93 ' '.join(args), os.path.join(dname, self.__script)))
94 self.contents.ensureCursorVisible()
95
96 program = args.pop(0)
97 self.__process.start(program, args)
98 procStarted = self.__process.waitForStarted()
99 if not procStarted:
100 E5MessageBox.critical(
101 self,
102 self.tr('Process Generation Error'),
103 self.tr(
104 'The process {0} could not be started. '
105 'Ensure, that it is in the search path.'
106 ).format(program))
107 return procStarted
108
109 @pyqtSlot(QAbstractButton)
110 def on_buttonBox_clicked(self, button):
111 """
112 Private slot called by a button of the button box clicked.
113
114 @param button button that was clicked
115 @type QAbstractButton
116 """
117 if button == self.buttonBox.button(QDialogButtonBox.Close):
118 self.accept()
119 elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
120 self.__finish()
121
122 def __finish(self):
123 """
124 Private slot called when the process was canceled by the user.
125
126 It is called when the process finished or
127 the user pressed the cancel button.
128 """
129 if self.__process is not None:
130 self.__process.disconnect(self.__finishedProcess)
131 self.__process.terminate()
132 QTimer.singleShot(2000, self.__process.kill)
133 self.__process.waitForFinished(3000)
134 self.__process = None
135
136 self.contents.insertPlainText(
137 self.tr('\n{0} aborted.\n').format(self.__cmdname))
138
139 self.__enableButtons()
140
141 def __finishedProcess(self):
142 """
143 Private slot called when the process finished.
144
145 It is called when the process finished or
146 the user pressed the cancel button.
147 """
148 if self.__process.exitStatus() == QProcess.NormalExit:
149 # add the spec file to the project
150 self.__project.addToOthers(
151 os.path.splitext(self.__script)[0] + ".spec")
152
153 self.__process = None
154
155 self.contents.insertPlainText(
156 self.tr('\n{0} finished.\n').format(self.__cmdname))
157
158 self.__enableButtons()
159
160 def __enableButtons(self):
161 """
162 Private slot called when all processes finished.
163
164 It is called when the process finished or
165 the user pressed the cancel button.
166 """
167 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
168 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
169 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
170 self.contents.ensureCursorVisible()
171
172 def __readStdout(self):
173 """
174 Private slot to handle the readyReadStandardOutput signal.
175
176 It reads the output of the process, formats it and inserts it into
177 the contents pane.
178 """
179 self.__process.setReadChannel(QProcess.StandardOutput)
180
181 while self.__process.canReadLine():
182 s = str(self.__process.readAllStandardOutput(),
183 Preferences.getSystem("IOEncoding"),
184 'replace')
185 self.contents.insertPlainText(s)
186 self.contents.ensureCursorVisible()
187
188 def __readStderr(self):
189 """
190 Private slot to handle the readyReadStandardError signal.
191
192 It reads the error output of the process and inserts it into the
193 error pane.
194 """
195 self.__process.setReadChannel(QProcess.StandardError)
196
197 while self.__process.canReadLine():
198 s = str(self.__process.readAllStandardError(),
199 Preferences.getSystem("IOEncoding"),
200 'replace')
201 self.contents.insertPlainText(s)
202 self.contents.ensureCursorVisible()

eric ide

mercurial