eric6/Plugins/WizardPlugins/SetupWizard/SetupWizardDialog.py

changeset 6942
2602857055c5
parent 6940
12ed1a714527
child 7005
342819f05839
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2013 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the setup.py wizard dialog.
8 """
9
10 from __future__ import unicode_literals
11 try:
12 str = unicode # __IGNORE_WARNING__
13 except NameError:
14 pass
15
16 import os
17 import sys
18 import datetime
19
20 from PyQt5.QtCore import pyqtSlot, Qt
21 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QTreeWidgetItem, \
22 QListWidgetItem, QApplication
23
24 from E5Gui.E5Application import e5App
25 from E5Gui import E5MessageBox, E5FileDialog
26 from E5Gui.E5Completers import E5DirCompleter
27
28 from .Ui_SetupWizardDialog import Ui_SetupWizardDialog
29
30 import UI.PixmapCache
31 import Utilities
32 import Preferences
33
34
35 class SetupWizardDialog(QDialog, Ui_SetupWizardDialog):
36 """
37 Class implementing the setup.py wizard dialog.
38
39 It displays a dialog for entering the parameters
40 for the E5MessageBox code generator.
41 """
42 def __init__(self, parent=None):
43 """
44 Constructor
45
46 @param parent reference to the parent widget (QWidget)
47 """
48 super(SetupWizardDialog, self).__init__(parent)
49 self.setupUi(self)
50
51 self.dataTabWidget.setCurrentIndex(0)
52
53 self.__packageDirCompleter = E5DirCompleter(self.packageEdit)
54 self.__packageRootDirCompleter = E5DirCompleter(self.packageRootEdit)
55 self.__sourceDirCompleter = E5DirCompleter(self.sourceDirectoryEdit)
56
57 self.packageRootDirButton.setIcon(UI.PixmapCache.getIcon("open.png"))
58 self.packageDirButton.setIcon(UI.PixmapCache.getIcon("open.png"))
59 self.sourceDirectoryButton.setIcon(UI.PixmapCache.getIcon("open.png"))
60
61 self.variantComboBox.addItem(self.tr("distutils"), "distutils.core")
62 self.variantComboBox.addItem(self.tr("setuptools"), "setuptools")
63 self.variantComboBox.setCurrentIndex(1)
64
65 self.__mandatoryStyleSheet = "QLineEdit {border: 2px solid;}"
66 for lineEdit in [self.nameEdit, self.versionEdit,
67 self.homePageUrlEdit, self.authorEdit,
68 self.authorEmailEdit, self.maintainerEdit,
69 self.maintainerEmailEdit]:
70 lineEdit.setStyleSheet(self.__mandatoryStyleSheet)
71
72 self.developmentStatusComboBox.addItem("", "")
73
74 self.__populateFromTroveLists()
75
76 self.licenseClassifierComboBox.setCurrentIndex(
77 self.licenseClassifierComboBox.findText(
78 "(GPLv3)", Qt.MatchContains | Qt.MatchCaseSensitive))
79
80 self.__okButton = self.buttonBox.button(QDialogButtonBox.Ok)
81 self.__okButton.setEnabled(False)
82
83 projectOpen = e5App().getObject("Project").isOpen()
84 self.projectButton.setEnabled(projectOpen)
85 self.autodiscoverPackagesButton.setEnabled(projectOpen)
86
87 self.homePageUrlEdit.textChanged.connect(self.__enableOkButton)
88 self.nameEdit.textChanged.connect(self.__enableOkButton)
89 self.versionEdit.textChanged.connect(self.__enableOkButton)
90 self.authorEdit.textChanged.connect(self.__enableOkButton)
91 self.authorEmailEdit.textChanged.connect(self.__enableOkButton)
92 self.maintainerEdit.textChanged.connect(self.__enableOkButton)
93 self.maintainerEmailEdit.textChanged.connect(self.__enableOkButton)
94
95 def __enableOkButton(self):
96 """
97 Private slot to set the state of the OK button.
98 """
99 enable = (
100 bool(self.nameEdit.text()) and
101 bool(self.versionEdit.text()) and
102 bool(self.homePageUrlEdit.text()) and
103 ((bool(self.authorEdit.text()) and
104 bool(self.authorEmailEdit.text())) or
105 (bool(self.maintainerEdit.text()) and
106 bool(self.maintainerEmailEdit.text()))) and
107 self.homePageUrlEdit.text().startswith(("http://", "https://"))
108 )
109
110 self.__okButton.setEnabled(enable)
111
112 def __populateFromTroveLists(self):
113 """
114 Private method to populate lists from the Trove list file.
115 """
116 filename = os.path.join(os.path.dirname(__file__),
117 "data", "trove_classifiers.txt")
118 try:
119 f = open(filename, "r")
120 lines = f.readlines()
121 f.close()
122 except (IOError, OSError) as err:
123 E5MessageBox.warning(
124 self,
125 self.tr("Reading Trove Classifiers"),
126 self.tr("""<p>The Trove Classifiers file <b>{0}</b>"""
127 """ could not be read.</p><p>Reason: {1}</p>""")
128 .format(filename, str(err)))
129 return
130
131 self.__classifiersDict = {}
132 for line in lines:
133 line = line.strip()
134 if line.startswith("License "):
135 self.licenseClassifierComboBox.addItem(
136 "/".join(line.split(" :: ")[1:]),
137 line
138 )
139 elif line.startswith("Development Status "):
140 self.developmentStatusComboBox.addItem(
141 line.split(" :: ")[1], line)
142 else:
143 self.__addClassifierEntry(line)
144 self.__classifiersDict = {}
145
146 def __addClassifierEntry(self, line):
147 """
148 Private method to add a new entry to the list of trove classifiers.
149
150 @param line line containing the data for the entry (string)
151 """
152 itm = None
153 pitm = None
154 dataList = line.split(" :: ")
155 for index in range(len(dataList)):
156 key = " :: ".join(dataList[:index + 1])
157 if key not in self.__classifiersDict:
158 if pitm is None:
159 itm = QTreeWidgetItem(
160 self.classifiersList, [dataList[index]])
161 pitm = itm
162 else:
163 itm = QTreeWidgetItem(pitm, [dataList[index]])
164 itm.setExpanded(True)
165 self.__classifiersDict[key] = itm
166 else:
167 pitm = self.__classifiersDict[key]
168 itm.setCheckState(0, Qt.Unchecked)
169 itm.setData(0, Qt.UserRole, line)
170
171 def __getLicenseText(self):
172 """
173 Private method to get the license text.
174
175 @return license text (string)
176 """
177 if not self.licenseClassifierCheckBox.isChecked():
178 return self.licenseEdit.text()
179 else:
180 lic = self.licenseClassifierComboBox.currentText()
181 if "(" in lic:
182 lic = lic.rsplit("(", 1)[1].split(")", 1)[0]
183 return lic
184
185 def getCode(self, indLevel, indString):
186 """
187 Public method to get the source code.
188
189 @param indLevel indentation level (int)
190 @param indString string used for indentation (space or tab) (string)
191 @return generated code (string)
192 """
193 # Note: all paths are created with '/'; setup will do the right thing
194
195 # calculate our indentation level and the indentation string
196 il = indLevel + 1
197 istring = il * indString
198 i1string = (il + 1) * indString
199 i2string = (il + 2) * indString
200 estring = os.linesep + indLevel * indString
201
202 # now generate the code
203 if self.introCheckBox.isChecked():
204 code = "#!/usr/bin/env python{0}{1}".format(
205 sys.version_info[0], os.linesep)
206 code += "# -*- coding: utf-8 -*-{0}{0}".format(os.linesep)
207 else:
208 code = ""
209
210 if self.metaDataCheckBox.isChecked():
211 code += '# metadata{0}'.format(os.linesep)
212 code += '"{0}"{1}'.format(
213 self.summaryEdit.text() or "Setup routine",
214 os.linesep
215 )
216 code += '__version__ = "{0}"{1}'.format(
217 self.versionEdit.text(), os.linesep)
218 code += '__license__ = "{0}"{1}'.format(
219 self.__getLicenseText(), os.linesep)
220 code += '__author__ = "{0}"{1}'.format(
221 self.authorEdit.text() or self.maintainerEdit.text(),
222 os.linesep)
223 code += '__email__ = "{0}"{1}'.format(
224 self.authorEmailEdit.text() or self.maintainerEmailEdit.text(),
225 os.linesep)
226 code += '__url__ = "{0}"{1}'.format(
227 self.homePageUrlEdit.text(), os.linesep)
228 code += '__date__ = "{0}"{1}'.format(
229 datetime.datetime.now().isoformat().split('.')[0], os.linesep)
230 code += '__prj__ = "{0}"{1}'.format(
231 self.nameEdit.text(), os.linesep)
232 code += os.linesep
233
234 if self.descriptionFromFilesCheckBox.isChecked():
235 code += "from __future__ import with_statement{0}".format(
236 os.linesep)
237
238 if self.importCheckBox.isChecked():
239 variant = self.variantComboBox.itemData(
240 self.variantComboBox.currentIndex())
241 if variant == "setuptools":
242 additionalImport = ", find_packages"
243 else:
244 additionalImport = ""
245 code += "from {0} import setup{1}{2}".format(
246 variant, additionalImport, os.linesep)
247 if code:
248 code += "{0}{0}".format(os.linesep)
249
250 if self.descriptionFromFilesCheckBox.isChecked():
251 code += 'def get_long_description():{0}'.format(os.linesep)
252 code += '{0}descr = []{1}'.format(istring, os.linesep)
253 code += '{0}for fname in "{1}":{2}'.format(
254 istring,
255 '", "'.join(self.descriptionEdit.toPlainText().splitlines()),
256 os.linesep)
257 code += '{0}{0}with open(fname) as f:{1}'.format(
258 istring, os.linesep)
259 code += '{0}{0}{0}descr.append(f.read()){1}'.format(
260 istring, os.linesep)
261 code += '{0}return "\\n\\n".join(descr){1}'.format(
262 istring, os.linesep)
263 code += "{0}{0}".format(os.linesep)
264
265 code += 'setup({0}'.format(os.linesep)
266 code += '{0}name="{1}",{2}'.format(
267 istring, self.nameEdit.text(), os.linesep)
268 code += '{0}version="{1}",{2}'.format(
269 istring, self.versionEdit.text(), os.linesep)
270
271 if self.summaryEdit.text():
272 code += '{0}description="{1}",{2}'.format(
273 istring, self.summaryEdit.text(), os.linesep)
274
275 if self.descriptionFromFilesCheckBox.isChecked():
276 code += '{0}long_description=get_long_description(),{1}'.format(
277 istring, os.linesep)
278 elif self.descriptionEdit.toPlainText():
279 code += '{0}long_description="""{1}""",{2}'.format(
280 istring, self.descriptionEdit.toPlainText(), os.linesep)
281
282 if self.authorEdit.text():
283 code += '{0}author="{1}",{2}'.format(
284 istring, self.authorEdit.text(), os.linesep)
285 code += '{0}author_email="{1}",{2}'.format(
286 istring, self.authorEmailEdit.text(), os.linesep)
287
288 if self.maintainerEdit.text():
289 code += '{0}maintainer="{1}",{2}'.format(
290 istring, self.maintainerEdit.text(), os.linesep)
291 code += '{0}maintainer_email="{1}",{2}'.format(
292 istring, self.maintainerEmailEdit.text(), os.linesep)
293
294 code += '{0}url="{1}",{2}'.format(
295 istring, self.homePageUrlEdit.text(), os.linesep)
296 if self.downloadUrlEdit.text():
297 code += '{0}download_url="{1}",{2}'.format(
298 istring, self.downloadUrlEdit.text(), os.linesep)
299
300 classifiers = []
301 if not self.licenseClassifierCheckBox.isChecked():
302 code += '{0}license="{1}",{2}'.format(
303 istring, self.licenseEdit.text(), os.linesep)
304 else:
305 classifiers.append(
306 self.licenseClassifierComboBox.itemData(
307 self.licenseClassifierComboBox.currentIndex()))
308
309 platforms = self.platformsEdit.toPlainText().splitlines()
310 if platforms:
311 code += '{0}platforms=[{1}'.format(istring, os.linesep)
312 code += '{0}"{1}"{2}'.format(
313 i1string,
314 '",{0}{1}"'.format(os.linesep, i1string).join(platforms),
315 os.linesep)
316 code += '{0}],{1}'.format(istring, os.linesep)
317
318 if self.developmentStatusComboBox.currentIndex() != 0:
319 classifiers.append(
320 self.developmentStatusComboBox.itemData(
321 self.developmentStatusComboBox.currentIndex()))
322
323 itm = self.classifiersList.topLevelItem(0)
324 while itm:
325 itm.setExpanded(True)
326 if itm.checkState(0) == Qt.Checked:
327 classifiers.append(itm.data(0, Qt.UserRole))
328 itm = self.classifiersList.itemBelow(itm)
329
330 # cleanup classifiers list - remove all invalid entries
331 classifiers = [c for c in classifiers if bool(c)]
332 if classifiers:
333 code += '{0}classifiers=[{1}'.format(istring, os.linesep)
334 code += '{0}"{1}"{2}'.format(
335 i1string,
336 '",{0}{1}"'.format(os.linesep, i1string).join(classifiers),
337 os.linesep)
338 code += '{0}],{1}'.format(istring, os.linesep)
339 del classifiers
340
341 if self.keywordsEdit.text():
342 code += '{0}keywords="{1}",{2}'.format(
343 istring, self.keywordsEdit.text(), os.linesep)
344
345 if self.variantComboBox.currentIndex() == 0:
346 # distutils
347 packages = []
348 for row in range(self.packagesList.count()):
349 packages.append(self.packagesList.item(row).text())
350 if packages:
351 code += '{0}packages=[{1}'.format(istring, os.linesep)
352 code += '{0}"{1}"{2}'.format(
353 i1string,
354 '",{0}{1}"'.format(os.linesep, i1string).join(packages),
355 os.linesep)
356 code += '{0}],{1}'.format(istring, os.linesep)
357 del packages
358 elif self.variantComboBox.currentIndex() == 1:
359 # setuptools
360 code += '{0}packages=find_packages('.format(istring)
361 src = Utilities.fromNativeSeparators(
362 self.sourceDirectoryEdit.text())
363 excludePatterns = []
364 for row in range(self.excludePatternList.count()):
365 excludePatterns.append(
366 self.excludePatternList.item(row).text())
367 if src:
368 code += '{0}{1}"{2}"'.format(os.linesep, i1string, src)
369 if excludePatterns:
370 code += ','
371 else:
372 code += '{0}{1}'.format(os.linesep, istring)
373 if excludePatterns:
374 code += '{0}{1}exclude=[{0}'.format(os.linesep, i1string)
375 code += '{0}"{1}"{2}'.format(
376 i2string,
377 '",{0}{1}"'.format(os.linesep, i2string)
378 .join(excludePatterns),
379 os.linesep)
380 code += '{0}]{1}{2}'.format(i1string, os.linesep, istring)
381 code += '),{0}'.format(os.linesep)
382
383 if self.includePackageDataCheckBox.isChecked():
384 code += '{0}include_package_data = True,{1}'.format(
385 istring, os.linesep)
386
387 modules = []
388 for row in range(self.modulesList.count()):
389 modules.append(self.modulesList.item(row).text())
390 if modules:
391 code += '{0}py_modules=[{1}'.format(istring, os.linesep)
392 code += '{0}"{1}"{2}'.format(
393 i1string,
394 '",{0}{1}"'.format(os.linesep, i1string).join(modules),
395 os.linesep)
396 code += '{0}],{1}'.format(istring, os.linesep)
397 del modules
398
399 scripts = []
400 for row in range(self.scriptsList.count()):
401 scripts.append(self.scriptsList.item(row).text())
402 if scripts:
403 code += '{0}scripts=[{1}'.format(istring, os.linesep)
404 code += '{0}"{1}"{2}'.format(
405 i1string,
406 '",{0}{1}"'.format(os.linesep, i1string).join(scripts),
407 os.linesep)
408 code += '{0}],{1}'.format(istring, os.linesep)
409 del scripts
410
411 code += "){0}".format(estring)
412 return code
413
414 @pyqtSlot()
415 def on_projectButton_clicked(self):
416 """
417 Private slot to populate some fields with data retrieved from the
418 current project.
419 """
420 project = e5App().getObject("Project")
421
422 self.nameEdit.setText(project.getProjectName())
423 try:
424 self.versionEdit.setText(project.getProjectVersion())
425 self.authorEdit.setText(project.getProjectAuthor())
426 self.authorEmailEdit.setText(project.getProjectAuthorEmail())
427 description = project.getProjectDescription()
428 except AttributeError:
429 self.versionEdit.setText(project.pdata["VERSION"][0])
430 self.authorEdit.setText(project.pdata["AUTHOR"][0])
431 self.authorEmailEdit.setText(project.pdata["EMAIL"][0])
432 description = project.pdata["DESCRIPTION"][0]
433
434 summary = description.split(".", 1)[0]\
435 .replace("\r", "").replace("\n", "") + "."
436 self.summaryEdit.setText(summary)
437 self.descriptionEdit.setPlainText(description)
438
439 self.packageRootEdit.setText(project.getProjectPath())
440
441 # prevent overwriting of entries by disabling the button
442 self.projectButton.setEnabled(False)
443
444 @pyqtSlot()
445 def on_packagesList_itemSelectionChanged(self):
446 """
447 Private slot to handle a change of selected items of the
448 packages list.
449 """
450 self.deletePackageButton.setEnabled(
451 len(self.packagesList.selectedItems()) > 0)
452
453 @pyqtSlot()
454 def on_deletePackageButton_clicked(self):
455 """
456 Private slot to delete the selected package items.
457 """
458 for itm in self.packagesList.selectedItems():
459 self.packagesList.takeItem(
460 self.packagesList.row(itm))
461 del itm
462
463 @pyqtSlot()
464 def on_addPackageButton_clicked(self):
465 """
466 Private slot to add a package to the list.
467 """
468 pkg = Utilities.toNativeSeparators(self.packageEdit.text())
469 self.__addPackage(pkg)
470
471 @pyqtSlot()
472 def on_packageEdit_returnPressed(self):
473 """
474 Private slot handling a press of the return button of the
475 package edit.
476 """
477 self.on_addPackageButton_clicked()
478
479 @pyqtSlot(str)
480 def on_packageEdit_textChanged(self, txt):
481 """
482 Private slot to handle a change of the package text.
483
484 @param txt text of the line edit (string)
485 """
486 self.addPackageButton.setEnabled(bool(txt))
487
488 @pyqtSlot()
489 def on_packageDirButton_clicked(self):
490 """
491 Private slot to select a package directory via a directory
492 selection dialog.
493 """
494 startDir = self.packageEdit.text()
495 if not startDir:
496 startDir = self.packageRootEdit.text() or self.__getStartDir()
497 packageDir = E5FileDialog.getExistingDirectory(
498 self,
499 self.tr("Package Directory"),
500 Utilities.fromNativeSeparators(startDir))
501 if packageDir:
502 self.packageEdit.setText(
503 Utilities.toNativeSeparators(packageDir))
504
505 @pyqtSlot()
506 def on_autodiscoverPackagesButton_clicked(self):
507 """
508 Private slot to discover packages automatically.
509 """
510 self.autodiscoverPackagesButton.setEnabled(False)
511 QApplication.setOverrideCursor(Qt.WaitCursor)
512 startDir = self.packageRootEdit.text() or self.__getStartDir()
513 if startDir:
514 self.packagesList.clear()
515 for dirpath, _dirnames, filenames in os.walk(startDir):
516 if "__init__.py" in filenames:
517 self.__addPackage(dirpath)
518 self.autodiscoverPackagesButton.setEnabled(True)
519 QApplication.restoreOverrideCursor()
520
521 @pyqtSlot()
522 def on_packageRootDirButton_clicked(self):
523 """
524 Private slot to select the packages root directory via a
525 directory selection dialog.
526 """
527 startDir = self.packageRootEdit.text()
528 if not startDir:
529 startDir = self.__getStartDir()
530 packagesRootDir = E5FileDialog.getExistingDirectory(
531 self,
532 self.tr("Packages Root Directory"),
533 Utilities.fromNativeSeparators(startDir),
534 E5FileDialog.Options(E5FileDialog.ShowDirsOnly))
535 if packagesRootDir:
536 self.packageRootEdit.setText(
537 Utilities.toNativeSeparators(packagesRootDir))
538
539 @pyqtSlot(str)
540 def on_packageRootEdit_textChanged(self, txt):
541 """
542 Private slot handling the entering of a packages root.
543
544 @param txt text of the line edit (string)
545 """
546 projectOpen = e5App().getObject("Project").isOpen()
547 validPackagesRoot = bool(txt) and os.path.exists(txt)
548 self.autodiscoverPackagesButton.setEnabled(
549 projectOpen or validPackagesRoot)
550
551 def __addPackage(self, pkgDir):
552 """
553 Private method to add a package to the list.
554
555 @param pkgDir name of the package directory (string)
556 """
557 if pkgDir:
558 if "\\" in pkgDir or "/" in pkgDir:
559 # It is a directory. Check for an __init__.py file.
560 if os.path.isabs(pkgDir):
561 prefix = ""
562 else:
563 prefix = self.packageRootEdit.text()
564 initName = os.path.join(
565 prefix,
566 Utilities.toNativeSeparators(pkgDir),
567 "__init__.py")
568 if not os.path.exists(initName):
569 res = E5MessageBox.information(
570 self,
571 self.tr("Add Package"),
572 self.tr("""<p>The directory <b>{0}</b> is not"""
573 """ a Python package.</p>""")
574 .format(pkgDir),
575 E5MessageBox.StandardButtons(
576 E5MessageBox.Ignore |
577 E5MessageBox.Ok))
578 if res == E5MessageBox.Ok:
579 return
580
581 pkg = pkgDir.replace(
582 Utilities.toNativeSeparators(self.packageRootEdit.text()), "")
583 if pkg.startswith(("\\", "/")):
584 pkg = pkg[1:]
585 if pkg:
586 QListWidgetItem(
587 pkg.replace("\\", ".").replace("/", "."),
588 self.packagesList)
589 self.packageEdit.clear()
590
591 def __getStartDir(self):
592 """
593 Private method to get the start directory for selection dialogs.
594
595 @return start directory (string)
596 """
597 return (Preferences.getMultiProject("Workspace") or
598 Utilities.getHomeDir())
599
600 @pyqtSlot()
601 def on_scriptsList_itemSelectionChanged(self):
602 """
603 Private slot to handle a change of selected items of the
604 scripts list.
605 """
606 self.deleteScriptButton.setEnabled(
607 len(self.scriptsList.selectedItems()) > 0)
608
609 @pyqtSlot()
610 def on_deleteScriptButton_clicked(self):
611 """
612 Private slot to delete the selected script items.
613 """
614 for itm in self.scriptsList.selectedItems():
615 self.scriptsList.takeItem(
616 self.scriptsList.row(itm))
617 del itm
618
619 @pyqtSlot()
620 def on_addScriptButton_clicked(self):
621 """
622 Private slot to add scripts to the list.
623 """
624 startDir = self.packageRootEdit.text() or self.__getStartDir()
625 scriptsList = E5FileDialog.getOpenFileNames(
626 self,
627 self.tr("Add Scripts"),
628 startDir,
629 self.tr("Python Files (*.py);;All Files(*)"))
630 for script in scriptsList:
631 script = script.replace(
632 Utilities.toNativeSeparators(startDir), "")
633 if script.startswith(("\\", "/")):
634 script = script[1:]
635 if script:
636 QListWidgetItem(Utilities.fromNativeSeparators(script),
637 self.scriptsList)
638
639 @pyqtSlot()
640 def on_modulesList_itemSelectionChanged(self):
641 """
642 Private slot to handle a change of selected items of the
643 modules list.
644 """
645 self.deleteModuleButton.setEnabled(
646 len(self.modulesList.selectedItems()) > 0)
647
648 @pyqtSlot()
649 def on_deleteModuleButton_clicked(self):
650 """
651 Private slot to delete the selected script items.
652 """
653 for itm in self.modulesList.selectedItems():
654 self.modulesList.takeItem(
655 self.modulesList.row(itm))
656 del itm
657
658 @pyqtSlot()
659 def on_addModuleButton_clicked(self):
660 """
661 Private slot to add Python modules to the list.
662 """
663 startDir = self.packageRootEdit.text() or self.__getStartDir()
664 modulesList = E5FileDialog.getOpenFileNames(
665 self,
666 self.tr("Add Python Modules"),
667 startDir,
668 self.tr("Python Files (*.py)"))
669 for module in modulesList:
670 module = module.replace(
671 Utilities.toNativeSeparators(startDir), "")
672 if module.startswith(("\\", "/")):
673 module = module[1:]
674 if module:
675 QListWidgetItem(os.path.splitext(module)[0]
676 .replace("\\", ".").replace("/", "."),
677 self.modulesList)
678
679 @pyqtSlot(int)
680 def on_variantComboBox_currentIndexChanged(self, index):
681 """
682 Private slot handling a change of the setup variant.
683
684 @param index index of the selected entry (integer)
685 """
686 self.packagesStackedWidget.setCurrentIndex(index)
687
688 @pyqtSlot()
689 def on_excludePatternList_itemSelectionChanged(self):
690 """
691 Private slot to handle a change of selected items of the
692 exclude pattern list.
693 """
694 self.deleteExcludePatternButton.setEnabled(
695 len(self.excludePatternList.selectedItems()) > 0)
696
697 @pyqtSlot()
698 def on_deleteExcludePatternButton_clicked(self):
699 """
700 Private slot to delete the selected exclude pattern items.
701 """
702 for itm in self.excludePatternList.selectedItems():
703 self.excludePatternList.takeItem(
704 self.excludePatternList.row(itm))
705 del itm
706
707 @pyqtSlot()
708 def on_addExludePatternButton_clicked(self):
709 """
710 Private slot to add an exclude pattern to the list.
711 """
712 pattern = self.excludePatternEdit.text()\
713 .replace("\\", ".").replace("/", ".")
714 if not self.excludePatternList.findItems(
715 pattern, Qt.MatchExactly | Qt.MatchCaseSensitive):
716 QListWidgetItem(pattern, self.excludePatternList)
717
718 @pyqtSlot(str)
719 def on_excludePatternEdit_textChanged(self, txt):
720 """
721 Private slot to handle a change of the exclude pattern text.
722
723 @param txt text of the line edit (string)
724 """
725 self.addExludePatternButton.setEnabled(bool(txt))
726
727 @pyqtSlot()
728 def on_excludePatternEdit_returnPressed(self):
729 """
730 Private slot handling a press of the return button of the
731 exclude pattern edit.
732 """
733 self.on_addExludePatternButton_clicked()
734
735 @pyqtSlot()
736 def on_sourceDirectoryButton_clicked(self):
737 """
738 Private slot to select the packages root directory via a
739 directory selection dialog.
740 """
741 startDir = self.sourceDirectoryEdit.text() or self.__getStartDir()
742 sourceDirectory = E5FileDialog.getExistingDirectory(
743 self,
744 self.tr("Source Directory"),
745 Utilities.fromNativeSeparators(startDir),
746 E5FileDialog.Options(E5FileDialog.ShowDirsOnly))
747 if sourceDirectory:
748 self.sourceDirectoryEdit.setText(
749 Utilities.toNativeSeparators(sourceDirectory))

eric ide

mercurial