PyInstaller/PyInstallerConfigDialog.py

changeset 4
52f0572b5908
parent 3
eb2d30b4d34e
child 5
8c92d66d20e4
equal deleted inserted replaced
3:eb2d30b4d34e 4:52f0572b5908
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2018 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
2 5
3 """ 6 """
4 Module implementing PyInstallerConfigDialog. 7 Module implementing PyInstallerConfigDialog.
5 """ 8 """
6 9
10 from __future__ import unicode_literals
11
12 import copy
13
7 from PyQt5.QtCore import pyqtSlot 14 from PyQt5.QtCore import pyqtSlot
8 from PyQt5.QtWidgets import QDialog 15 from PyQt5.QtWidgets import QDialog, QDialogButtonBox
9 16
10 from E5Gui.E5PathPicker import E5PathPickerModes 17 from E5Gui.E5PathPicker import E5PathPickerModes
11 18
12 from .Ui_PyInstallerConfigDialog import Ui_PyInstallerConfigDialog 19 from .Ui_PyInstallerConfigDialog import Ui_PyInstallerConfigDialog
13 20
14 import Globals 21 import Globals
15 22
16 23
17 class PyInstallerConfigDialog(QDialog, Ui_PyInstallerConfigDialog): 24 class PyInstallerConfigDialog(QDialog, Ui_PyInstallerConfigDialog):
18 """ 25 """
19 Class documentation goes here. 26 Class implementing a dialog to enter the parameters for pyinstaller
27 and pyi-makespec.
20 """ 28 """
21 def __init__(self, project, executables, params=None, mode="installer", 29 def __init__(self, project, executables, params=None, mode="installer",
22 parent=None): 30 parent=None):
23 """ 31 """
24 Constructor 32 Constructor
37 assert mode in ("installer", "spec") 45 assert mode in ("installer", "spec")
38 46
39 super(PyInstallerConfigDialog, self).__init__(parent) 47 super(PyInstallerConfigDialog, self).__init__(parent)
40 self.setupUi(self) 48 self.setupUi(self)
41 49
50 self.__project = project
51 self.__mode = mode
52
42 self.inputFilePicker.setMode(E5PathPickerModes.OpenFileMode) 53 self.inputFilePicker.setMode(E5PathPickerModes.OpenFileMode)
43 self.inputFilePicker.setFilters(self.tr( 54 self.inputFilePicker.setDefaultDirectory(
44 "Python Files (*.py *.py2 *.py3);;" 55 self.__project.getProjectPath())
45 "Python GUI Files (*.pyw *.pyw2 *.pyw3);;" 56 if self.__mode == "installer":
46 "Spec Files (*.spec);;" 57 self.inputFilePicker.setFilters(self.tr(
47 "All Files (*)" 58 "Python Files (*.py *.py2 *.py3);;"
48 )) 59 "Python GUI Files (*.pyw *.pyw2 *.pyw3);;"
60 "Spec Files (*.spec);;"
61 "All Files (*)"
62 ))
63 elif self.__mode == "spec":
64 self.inputFilePicker.setFilters(self.tr(
65 "Python Files (*.py *.py2 *.py3);;"
66 "Python GUI Files (*.pyw *.pyw2 *.pyw3);;"
67 "All Files (*)"
68 ))
49 69
50 self.executableCombo.addItems(executables) 70 self.executableCombo.addItems(executables)
51 71
52 self.__project = project 72 if not bool(project.getMainScript()):
53 if project.getMainScript() == "":
54 # no main script defined 73 # no main script defined
55 self.selectedScriptButton.setChecke(True) 74 self.selectedScriptButton.setChecked(True)
56 self.mainScriptButton.setEnabled(False) 75 self.mainScriptButton.setEnabled(False)
57 76
58 self.iconFilePicker.setMode(E5PathPickerModes.OpenFileMode) 77 self.iconFilePicker.setMode(E5PathPickerModes.OpenFileMode)
78 self.iconFilePicker.setDefaultDirectory(
79 self.__project.getProjectPath())
59 if Globals.isMacPlatform(): 80 if Globals.isMacPlatform():
60 self.iconFilePicker.setFilters(self.tr( 81 self.iconFilePicker.setFilters(self.tr(
61 "Icon Files (*.icns);;" 82 "Icon Files (*.icns);;"
62 "All Files (*)" 83 "All Files (*)"
63 )) 84 ))
66 "Icon Files (*.ico);;" 87 "Icon Files (*.ico);;"
67 "Executable Files (*.exe);;" 88 "Executable Files (*.exe);;"
68 "All Files (*)" 89 "All Files (*)"
69 )) 90 ))
70 91
92 # disable platform specific tabs
71 self.tabWidget.setTabEnabled( 93 self.tabWidget.setTabEnabled(
72 1, 94 self.tabWidget.indexOf(self.windowsMacTab),
73 Globals.isMacPlatform() or Globals.isWindowsPlatform()) 95 Globals.isMacPlatform() or Globals.isWindowsPlatform())
74 self.tabWidget.setTabEnabled( 96 self.tabWidget.setTabEnabled(
75 2, 97 self.tabWidget.indexOf(self.macTab),
76 Globals.isMacPlatform()) 98 Globals.isMacPlatform())
99
100 self.__initializeDefaults()
101
102 # get a copy of the defaults to store the user settings
103 self.__parameters = copy.deepcopy(self.__defaults)
104
105 # combine it with the values of params
106 if params is not None:
107 for key, value in params.items():
108 if key in self.__parameters:
109 self.__parameters[key] = params[key]
110
111 # initialize general tab
112 if mode == "installer" and bool(self.__parameters["pyinstaller"]):
113 self.executableCombo.setCurrentIndex(
114 self.executableCombo.findText(
115 self.__parameters["pyinstaller"]))
116 elif mode == "spec" and bool(self.__parameters["pyi-makespec"]):
117 self.executableCombo.setCurrentIndex(
118 self.executableCombo.findText(
119 self.__parameters["pyi-makespec"]))
120 if self.__parameters["mainscript"]:
121 self.mainScriptButton.setChecked(True)
122 else:
123 self.selectedScriptButton.setChecked(True)
124 self.inputFilePicker.setText(self.__parameters["inputFile"])
125 if self.__parameters["oneDirectory"]:
126 self.oneDirButton.setChecked(True)
127 else:
128 self.oneFileButton.setChecked(True)
129 self.nameEdit.setText(self.__parameters["name"])
130 self.keyEdit.setText(self.__parameters["encryptionKey"])
131 self.cleanCheckBox.setChecked(self.__parameters["cleanBeforeBuilding"])
132
133 # initialize Windows and macOS tab
134 if self.__parameters["consoleApplication"]:
135 self.consoleButton.setChecked(True)
136 else:
137 self.windowedButton.setChecked(True)
138 self.iconFilePicker.setText(self.__parameters["iconFile"])
139 self.iconIdEdit.setText(self.__parameters["iconId"])
140
141 # initialize maxOS specific tab
142 self.bundleIdentifierEdit.setText(
143 self.__parameters["bundleIdentifier"])
144
145 self.__updateOkButton()
146
147 msh = self.minimumSizeHint()
148 self.resize(max(self.width(), msh.width()), msh.height())
149
150 def __initializeDefaults(self):
151 """
152 Private method to set the default values.
153
154 These are needed later on to generate the command line parameters.
155 """
156 self.__defaults = {
157 # general options
158 "pyinstaller": "",
159 "pyi-makespec": "",
160 "mainscript": bool(self.__project.getMainScript()),
161 "inputFile": "",
162 "oneDirectory": True,
163 "name": "",
164 "encryptionKey": "",
165 "cleanBeforeBuilding": False,
166
167 # Windows and macOS options
168 "consoleApplication": True,
169 "iconFile": "",
170 "iconId": "",
171
172 # macOS specific options
173 "bundleIdentifier": "",
174 }
175
176 def generateParameters(self):
177 """
178 Public method that generates the command line parameters.
179
180 It generates a list of strings to be used to set the QProcess arguments
181 for the pyinstaller call and a list containing the non default
182 parameters. The second list can be passed back upon object generation
183 to overwrite the default settings.
184
185 @return a tuple of the command line parameters and non default
186 parameters
187 @rtype tuple of (list of str, dict)
188 """
189 parms = {}
190 args = []
191
192 # 1. the program name
193 if self.__mode == "installer":
194 args.append(self.__parameters["pyinstaller"])
195 parms["pyinstaller"] = self.__parameters["pyinstaller"]
196 elif self.__mode == "spec":
197 args.append(self.__parameters["pyi-makespec"])
198 parms["pyi-makespec"] = self.__parameters["pyi-makespec"]
199
200 # 2. the commandline options
201 # 2.1 general options, input
202 if not self.__parameters["mainscript"]:
203 parms["mainscript"] = False
204 parms["inputFile"] = self.__parameters["inputFile"]
205
206 runWithSpec = self.__parameters["inputFile"].endswith(".spec")
207 if not runWithSpec:
208 # 2.2 general options, part 1
209 if not self.__parameters["oneDirectory"]:
210 parms["oneDirectory"] = self.__parameters["oneDirectory"]
211 args.append("--onefile")
212 if self.__parameters["name"] != self.__defaults["name"]:
213 parms["name"] = self.__parameters["name"]
214 args.append("--name")
215 args.append(self.__parameters["name"])
216 if self.__parameters["encryptionKey"] != \
217 self.__defaults["encryptionKey"]:
218 parms["encryptionKey"] = self.__parameters["encryptionKey"]
219 args.append("--key")
220 args.append(self.__parameters["encryptionKey"])
221
222 # 2.3 Windows and macOS options
223 if self.__parameters["consoleApplication"] != \
224 self.__defaults["consoleApplication"]:
225 parms["consoleApplication"] = \
226 self.__parameters["consoleApplication"]
227 args.append("--windowed")
228 if self.__parameters["iconFile"] != self.__defaults["iconFile"]:
229 parms["iconFile"] = self.__parameters["iconFile"]
230 parms["iconId"] = self.__parameters["iconId"]
231 args.append("--icon")
232 if self.__parameters["iconFile"].endswith(".exe"):
233 if bool(self.__parameters["iconId"]):
234 iconId = self.__parameters["iconId"]
235 else:
236 iconId = "0"
237 args.append("{0},{1}".format(
238 self.__parameters["iconFile"], iconId))
239 else:
240 args.append(self.__parameters["iconFile"])
241
242 # 2.4 macOS specific options
243 if self.__parameters["bundleIdentifier"] != \
244 self.__defaults["bundleIdentifier"]:
245 parms["bundleIdentifier"] = \
246 self.__parameters["bundleIdentifier"]
247 args.append("--osx-bundle-identifier")
248 args.append(self.__parameters["bundleIdentifier"])
249
250 # 2.5 general options, part 2
251 if self.__parameters["cleanBeforeBuilding"] != \
252 self.__defaults["cleanBeforeBuilding"]:
253 parms["cleanBeforeBuilding"] = \
254 self.__parameters["cleanBeforeBuilding"]
255 args.append("--clean")
256
257 # 3. always add these arguments
258 args.append("--noconfirm") # don't ask the user
259
260 # finalize the arguments array
261 if self.__parameters["mainscript"]:
262 args.append(self.__project.getMainScript())
263 else:
264 args.append(self.__parameters["inputFile"])
265
266 return args, parms
267
268 def accept(self):
269 """
270 Public method called by the Ok button.
271
272 It saves the values in the parameters dictionary.
273 """
274 # get data of general tab
275 if self.__mode == "installer":
276 self.__parameters["pyinstaller"] = \
277 self.executableCombo.currentText()
278 elif self.__mode == "spec":
279 self.__parameters["pyi-makespec"] = \
280 self.executableCombo.currentText()
281 self.__parameters["mainscript"] = self.mainScriptButton.isChecked()
282 self.__parameters["inputFile"] = self.inputFilePicker.text()
283 self.__parameters["oneDirectory"] = self.oneDirButton.isChecked()
284 self.__parameters["name"] = self.nameEdit.text()
285 self.__parameters["encryptionKey"] = self.keyEdit.text()
286 self.__parameters["cleanBeforeBuilding"] = \
287 self.cleanCheckBox.isChecked()
288
289 # get data of Windows and macOS tab
290 self.__parameters["consoleApplication"] = \
291 self.consoleButton.isChecked()
292 self.__parameters["iconFile"] = self.iconFilePicker.text()
293 self.__parameters["iconId"] = self.iconIdEdit.text()
294
295 # get data of macOS specific tab
296 self.__parameters["bundleIdentifier"] = \
297 self.bundleIdentifierEdit.text()
298
299 # call the accept slot of the base class
300 super(PyInstallerConfigDialog, self).accept()
301
302 def __updateOkButton(self):
303 """
304 Private method to update the enabled state of the OK button.
305 """
306 enable = True
307
308 # If not to be run with the project main script, a script or
309 # spec file must be selected.
310 if self.selectedScriptButton.isChecked() and \
311 not bool(self.inputFilePicker.text()):
312 enable = False
313
314 # If the icon shall be picked from a .exe file, an icon ID
315 # must be entered (Windows only).
316 if self.iconFilePicker.text().endswith(".exe") and \
317 not bool(self.iconIdEdit.text()):
318 enable = False
319
320 self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(enable)
321
322 @pyqtSlot(bool)
323 def on_selectedScriptButton_toggled(self, checked):
324 """
325 Private slot to handle changes of the radio button state.
326
327 @param checked state of the radio button
328 @type bool
329 """
330 self.__updateOkButton()
331
332 @pyqtSlot(str)
333 def on_inputFilePicker_textChanged(self, txt):
334 """
335 Private slot to handle changes of the input file.
336
337 @param txt text of the file edit
338 @type str
339 """
340 self.__updateOkButton()
341
342 @pyqtSlot(str)
343 def on_iconFilePicker_textChanged(self, txt):
344 """
345 Private slot to handle changes of the icon file.
346
347 @param txt text of the file edit
348 @type str
349 """
350 self.iconIdEdit.setEnabled(txt.endswith(".exe"))
351 self.__updateOkButton()
352
353 @pyqtSlot(str)
354 def on_iconIdEdit_textChanged(self, txt):
355 """
356 Private slot to handle changes of the icon ID.
357
358 @param txt iconID
359 @type str
360 """
361 self.__updateOkButton()

eric ide

mercurial