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() |