Project/Project.py

branch
Py2 comp.
changeset 3057
10516539f238
parent 3056
9986ec0e559a
parent 3010
befeff46ec0f
child 3058
0a02c433f52d
equal deleted inserted replaced
3056:9986ec0e559a 3057:10516539f238
19 import glob 19 import glob
20 import fnmatch 20 import fnmatch
21 import copy 21 import copy
22 import zipfile 22 import zipfile
23 23
24 from PyQt4.QtCore import QFile, QFileInfo, pyqtSignal, QCryptographicHash, QIODevice, \ 24 from PyQt4.QtCore import QFile, QFileInfo, pyqtSignal, QCryptographicHash, \
25 QByteArray, QObject, Qt 25 QIODevice, QByteArray, QObject, Qt
26 from PyQt4.QtGui import QCursor, QLineEdit, QToolBar, QDialog, QInputDialog, \ 26 from PyQt4.QtGui import QCursor, QLineEdit, QToolBar, QDialog, QInputDialog, \
27 QApplication, QMenu, QAction 27 QApplication, QMenu, QAction
28 from PyQt4.Qsci import QsciScintilla 28 from PyQt4.Qsci import QsciScintilla
29 29
30 from E5Gui.E5Application import e5App 30 from E5Gui.E5Application import e5App
44 """ 44 """
45 Class implementing the project management functionality. 45 Class implementing the project management functionality.
46 46
47 @signal dirty(int) emitted when the dirty state changes 47 @signal dirty(int) emitted when the dirty state changes
48 @signal projectLanguageAdded(str) emitted after a new language was added 48 @signal projectLanguageAdded(str) emitted after a new language was added
49 @signal projectLanguageAddedByCode(str) emitted after a new language was added. 49 @signal projectLanguageAddedByCode(str) emitted after a new language was
50 The language code is sent by this signal. 50 added. The language code is sent by this signal.
51 @signal projectLanguageRemoved(str) emitted after a language was removed 51 @signal projectLanguageRemoved(str) emitted after a language was removed
52 @signal projectFormAdded(str) emitted after a new form was added 52 @signal projectFormAdded(str) emitted after a new form was added
53 @signal projectFormRemoved(str) emitted after a form was removed 53 @signal projectFormRemoved(str) emitted after a form was removed
54 @signal projectFormCompiled(str) emitted after a form was compiled 54 @signal projectFormCompiled(str) emitted after a form was compiled
55 @signal projectSourceAdded(str) emitted after a new source file was added 55 @signal projectSourceAdded(str) emitted after a new source file was added
56 @signal projectSourceRemoved(str) emitted after a source was removed 56 @signal projectSourceRemoved(str) emitted after a source was removed
57 @signal projectInterfaceAdded(str) emitted after a new IDL file was added 57 @signal projectInterfaceAdded(str) emitted after a new IDL file was added
58 @signal projectInterfaceRemoved(str) emitted after a IDL file was removed 58 @signal projectInterfaceRemoved(str) emitted after a IDL file was removed
59 @signal projectResourceAdded(str) emitted after a new resource file was added 59 @signal projectResourceAdded(str) emitted after a new resource file was
60 added
60 @signal projectResourceRemoved(str) emitted after a resource was removed 61 @signal projectResourceRemoved(str) emitted after a resource was removed
61 @signal projectOthersAdded(str) emitted after a file or directory was added 62 @signal projectOthersAdded(str) emitted after a file or directory was added
62 to the OTHERS project data area 63 to the OTHERS project data area
63 @signal projectOthersRemoved(str) emitted after a file was removed from the 64 @signal projectOthersRemoved(str) emitted after a file was removed from the
64 OTHERS project data area 65 OTHERS project data area
65 @signal projectAboutToBeCreated() emitted just before the project will be created 66 @signal projectAboutToBeCreated() emitted just before the project will be
66 @signal newProjectHooks() emitted after a new project was generated but before 67 created
67 the newProject() signal is sent 68 @signal newProjectHooks() emitted after a new project was generated but
69 before the newProject() signal is sent
68 @signal newProject() emitted after a new project was generated 70 @signal newProject() emitted after a new project was generated
69 @signal sourceFile(str) emitted after a project file was read to 71 @signal sourceFile(str) emitted after a project file was read to
70 open the main script 72 open the main script
71 @signal projectOpenedHooks() emitted after a project file was read but before the 73 @signal projectOpenedHooks() emitted after a project file was read but
72 projectOpened() signal is sent 74 before the projectOpened() signal is sent
73 @signal projectOpened() emitted after a project file was read 75 @signal projectOpened() emitted after a project file was read
74 @signal projectClosedHooks() emitted after a project file was closed but before the 76 @signal projectClosedHooks() emitted after a project file was closed but
75 projectClosed() signal is sent 77 before the projectClosed() signal is sent
76 @signal projectClosed() emitted after a project was closed 78 @signal projectClosed() emitted after a project was closed
77 @signal projectFileRenamed(str, str) emitted after a file of the project 79 @signal projectFileRenamed(str, str) emitted after a file of the project
78 has been renamed 80 has been renamed
79 @signal projectPropertiesChanged() emitted after the project properties were changed 81 @signal projectPropertiesChanged() emitted after the project properties
80 @signal directoryRemoved(str) emitted after a directory has been removed from 82 were changed
81 the project 83 @signal directoryRemoved(str) emitted after a directory has been removed
84 from the project
82 @signal prepareRepopulateItem(str) emitted before an item of the model is 85 @signal prepareRepopulateItem(str) emitted before an item of the model is
83 repopulated 86 repopulated
84 @signal completeRepopulateItem(str) emitted after an item of the model was 87 @signal completeRepopulateItem(str) emitted after an item of the model was
85 repopulated 88 repopulated
86 @signal vcsStatusMonitorStatus(str, str) emitted to signal the status of the 89 @signal vcsStatusMonitorStatus(str, str) emitted to signal the status of
87 monitoring thread (ok, nok, op, off) and a status message 90 the monitoring thread (ok, nok, op, off) and a status message
88 @signal reinitVCS() emitted after the VCS has been reinitialized 91 @signal reinitVCS() emitted after the VCS has been reinitialized
89 @signal showMenu(str, QMenu) emitted when a menu is about to be shown. The name 92 @signal showMenu(str, QMenu) emitted when a menu is about to be shown. The
90 of the menu and a reference to the menu are given. 93 name of the menu and a reference to the menu are given.
91 @signal lexerAssociationsChanged() emitted after the lexer associations have been 94 @signal lexerAssociationsChanged() emitted after the lexer associations
92 changed 95 have been changed
93 @signal projectChanged() emitted to signal a change of the project 96 @signal projectChanged() emitted to signal a change of the project
94 """ 97 """
95 dirty = pyqtSignal(int) 98 dirty = pyqtSignal(int)
96 projectLanguageAdded = pyqtSignal(str) 99 projectLanguageAdded = pyqtSignal(str)
97 projectLanguageAddedByCode = pyqtSignal(str) 100 projectLanguageAddedByCode = pyqtSignal(str)
241 self.__projectTypes["E4Plugin"] = self.trUtf8("Eric Plugin") 244 self.__projectTypes["E4Plugin"] = self.trUtf8("Eric Plugin")
242 self.__projectTypes["Console"] = self.trUtf8("Console") 245 self.__projectTypes["Console"] = self.trUtf8("Console")
243 self.__projectTypes["Other"] = self.trUtf8("Other") 246 self.__projectTypes["Other"] = self.trUtf8("Other")
244 247
245 self.__projectProgLanguages = { 248 self.__projectProgLanguages = {
246 "Python2": ["Qt4", "Qt4C", "PyQt5", "PyQt5C", "E4Plugin", "Console", "Other"], 249 "Python2": ["Qt4", "Qt4C", "PyQt5", "PyQt5C", "E4Plugin",
247 "Python3": ["Qt4", "Qt4C", "PyQt5", "PyQt5C", "E4Plugin", "Console", "Other"], 250 "Console", "Other"],
251 "Python3": ["Qt4", "Qt4C", "PyQt5", "PyQt5C", "E4Plugin",
252 "Console", "Other"],
248 "Ruby": ["Qt4", "Qt4C", "Console", "Other"], 253 "Ruby": ["Qt4", "Qt4C", "Console", "Other"],
249 } 254 }
250 255
251 pyside2, pyside3 = Utilities.checkPyside() 256 pyside2, pyside3 = Utilities.checkPyside()
252 if pyside2 or pyside3: 257 if pyside2 or pyside3:
253 self.__projectTypes["PySide"] = self.trUtf8("PySide GUI") 258 self.__projectTypes["PySide"] = self.trUtf8("PySide GUI")
254 self.__projectTypes["PySideC"] = self.trUtf8("PySide Console") 259 self.__projectTypes["PySideC"] = self.trUtf8("PySide Console")
255 if pyside2: 260 if pyside2:
256 self.__projectProgLanguages["Python2"].extend(["PySide", "PySideC"]) 261 self.__projectProgLanguages["Python2"].extend(
262 ["PySide", "PySideC"])
257 if pyside3: 263 if pyside3:
258 self.__projectProgLanguages["Python3"].extend(["PySide", "PySideC"]) 264 self.__projectProgLanguages["Python3"].extend(
265 ["PySide", "PySideC"])
259 266
260 def getProjectTypes(self, progLanguage=""): 267 def getProjectTypes(self, progLanguage=""):
261 """ 268 """
262 Public method to get the list of supported project types. 269 Public method to get the list of supported project types.
263 270
264 @param progLanguage programming language to get project types for (string) 271 @param progLanguage programming language to get project types for
272 (string)
265 @return reference to the dictionary of project types. 273 @return reference to the dictionary of project types.
266 """ 274 """
267 if progLanguage and progLanguage in self.__projectProgLanguages: 275 if progLanguage and progLanguage in self.__projectProgLanguages:
268 ptypes = {} 276 ptypes = {}
269 for ptype in self.__projectProgLanguages[progLanguage]: 277 for ptype in self.__projectProgLanguages[progLanguage]:
294 302
295 @param type_ internal type designator to be registered (string) 303 @param type_ internal type designator to be registered (string)
296 @param description more verbose type name (display string) (string) 304 @param description more verbose type name (display string) (string)
297 @keyparam fileTypeCallback reference to a method returning a dictionary 305 @keyparam fileTypeCallback reference to a method returning a dictionary
298 of filetype associations. 306 of filetype associations.
299 @keyparam binaryTranslationsCallback reference to a method returning the 307 @keyparam binaryTranslationsCallback reference to a method returning
300 name of the binary translation file given the name of the raw 308 the name of the binary translation file given the name of the raw
301 translation file 309 translation file
302 @keyparam lexerAssociationCallback reference to a method returning the 310 @keyparam lexerAssociationCallback reference to a method returning the
303 lexer type to be used for syntax highlighting given the name of 311 lexer type to be used for syntax highlighting given the name of
304 a file 312 a file
305 @keyparam progLanguages programming languages supported by the 313 @keyparam progLanguages programming languages supported by the
308 if progLanguages: 316 if progLanguages:
309 for progLanguage in progLanguages: 317 for progLanguage in progLanguages:
310 if progLanguage not in self.__projectProgLanguages: 318 if progLanguage not in self.__projectProgLanguages:
311 E5MessageBox.critical(self.ui, 319 E5MessageBox.critical(self.ui,
312 self.trUtf8("Registering Project Type"), 320 self.trUtf8("Registering Project Type"),
313 self.trUtf8("""<p>The Programming Language <b>{0}</b> is not""" 321 self.trUtf8(
314 """ supported.</p>""")\ 322 """<p>The Programming Language <b>{0}</b> is not"""
323 """ supported.</p>""")\
315 .format(progLanguage) 324 .format(progLanguage)
316 ) 325 )
317 return 326 return
318 327
319 if type_ in self.__projectProgLanguages[progLanguage]: 328 if type_ in self.__projectProgLanguages[progLanguage]:
320 E5MessageBox.critical(self.ui, 329 E5MessageBox.critical(self.ui,
321 self.trUtf8("Registering Project Type"), 330 self.trUtf8("Registering Project Type"),
322 self.trUtf8("""<p>The Project type <b>{0}</b> is already""" 331 self.trUtf8(
323 """ registered with Programming Language""" 332 """<p>The Project type <b>{0}</b> is already"""
324 """ <b>{1}</b>.</p>""")\ 333 """ registered with Programming Language"""
334 """ <b>{1}</b>.</p>""")\
325 .format(type_, progLanguage) 335 .format(type_, progLanguage)
326 ) 336 )
327 return 337 return
328 338
329 if type_ in self.__projectTypes: 339 if type_ in self.__projectTypes:
334 ) 344 )
335 else: 345 else:
336 self.__projectTypes[type_] = description 346 self.__projectTypes[type_] = description
337 self.__fileTypeCallbacks[type_] = fileTypeCallback 347 self.__fileTypeCallbacks[type_] = fileTypeCallback
338 self.__lexerAssociationCallbacks[type_] = lexerAssociationCallback 348 self.__lexerAssociationCallbacks[type_] = lexerAssociationCallback
339 self.__binaryTranslationsCallbacks[type_] = binaryTranslationsCallback 349 self.__binaryTranslationsCallbacks[type_] = \
350 binaryTranslationsCallback
340 if progLanguages: 351 if progLanguages:
341 for progLanguage in progLanguages: 352 for progLanguage in progLanguages:
342 self.__projectProgLanguages[progLanguage].append(type_) 353 self.__projectProgLanguages[progLanguage].append(type_)
343 else: 354 else:
344 # no specific programming languages given -> add to all 355 # no specific programming languages given -> add to all
372 self.pfile = "" # name of the project file 383 self.pfile = "" # name of the project file
373 self.ppath = "" # name of the project directory 384 self.ppath = "" # name of the project directory
374 self.translationsRoot = "" # the translations prefix 385 self.translationsRoot = "" # the translations prefix
375 self.name = "" 386 self.name = ""
376 self.opened = False 387 self.opened = False
377 self.subdirs = [""] # record the project dir as a relative path (i.e. empty path) 388 self.subdirs = [""] # record the project dir as a relative path
389 # (i.e. empty path)
378 self.otherssubdirs = [] 390 self.otherssubdirs = []
379 self.vcs = None 391 self.vcs = None
380 self.vcsRequested = False 392 self.vcsRequested = False
381 self.dbgCmdline = '' 393 self.dbgCmdline = ''
382 self.dbgWd = '' 394 self.dbgWd = ''
421 def getData(self, category, key): 433 def getData(self, category, key):
422 """ 434 """
423 Public method to get data out of the project data store. 435 Public method to get data out of the project data store.
424 436
425 @param category category of the data to get (string, one of 437 @param category category of the data to get (string, one of
426 PROJECTTYPESPECIFICDATA, CHECKERSPARMS, PACKAGERSPARMS, DOCUMENTATIONPARMS 438 PROJECTTYPESPECIFICDATA, CHECKERSPARMS, PACKAGERSPARMS,
427 or OTHERTOOLSPARMS) 439 DOCUMENTATIONPARMS or OTHERTOOLSPARMS)
428 @param key key of the data entry to get (string). 440 @param key key of the data entry to get (string).
429 @return a copy of the requested data or None 441 @return a copy of the requested data or None
430 """ 442 """
431 if category in ["PROJECTTYPESPECIFICDATA", "CHECKERSPARMS", "PACKAGERSPARMS", 443 if category in ["PROJECTTYPESPECIFICDATA", "CHECKERSPARMS",
432 "DOCUMENTATIONPARMS", "OTHERTOOLSPARMS"] and \ 444 "PACKAGERSPARMS", "DOCUMENTATIONPARMS",
445 "OTHERTOOLSPARMS"] and \
433 key in self.pdata[category]: 446 key in self.pdata[category]:
434 return copy.deepcopy(self.pdata[category][key]) 447 return copy.deepcopy(self.pdata[category][key])
435 else: 448 else:
436 return None 449 return None
437 450
438 def setData(self, category, key, data): 451 def setData(self, category, key, data):
439 """ 452 """
440 Public method to store data in the project data store. 453 Public method to store data in the project data store.
441 454
442 @param category category of the data to get (string, one of 455 @param category category of the data to get (string, one of
443 PROJECTTYPESPECIFICDATA, CHECKERSPARMS, PACKAGERSPARMS, DOCUMENTATIONPARMS 456 PROJECTTYPESPECIFICDATA, CHECKERSPARMS, PACKAGERSPARMS,
444 or OTHERTOOLSPARMS) 457 DOCUMENTATIONPARMS or OTHERTOOLSPARMS)
445 @param key key of the data entry to get (string). 458 @param key key of the data entry to get (string).
446 @param data data to be stored 459 @param data data to be stored
447 @return flag indicating success (boolean) 460 @return flag indicating success (boolean)
448 """ 461 """
449 if category not in ["PROJECTTYPESPECIFICDATA", "CHECKERSPARMS", "PACKAGERSPARMS", 462 if category not in ["PROJECTTYPESPECIFICDATA", "CHECKERSPARMS",
450 "DOCUMENTATIONPARMS", "OTHERTOOLSPARMS"]: 463 "PACKAGERSPARMS", "DOCUMENTATIONPARMS",
464 "OTHERTOOLSPARMS"]:
451 return False 465 return False
452 466
453 # test for changes of data and save them in the project 467 # test for changes of data and save them in the project
454 # 1. there were none, now there are 468 # 1. there were none, now there are
455 if key not in self.pdata[category] and len(data) > 0: 469 if key not in self.pdata[category] and len(data) > 0:
469 return False 483 return False
470 return True 484 return True
471 485
472 def initFileTypes(self): 486 def initFileTypes(self):
473 """ 487 """
474 Public method to initialize the filetype associations with default values. 488 Public method to initialize the filetype associations with default
489 values.
475 """ 490 """
476 self.pdata["FILETYPES"] = {} 491 self.pdata["FILETYPES"] = {}
477 if self.pdata["MIXEDLANGUAGE"][0]: 492 if self.pdata["MIXEDLANGUAGE"][0]:
478 sourceKey = "Mixed" 493 sourceKey = "Mixed"
479 else: 494 else:
480 sourceKey = self.pdata["PROGLANGUAGE"][0] 495 sourceKey = self.pdata["PROGLANGUAGE"][0]
481 for ext in self.sourceExtensions[sourceKey]: 496 for ext in self.sourceExtensions[sourceKey]:
482 self.pdata["FILETYPES"]["*{0}".format(ext)] = "SOURCES" 497 self.pdata["FILETYPES"]["*{0}".format(ext)] = "SOURCES"
483 self.pdata["FILETYPES"]["*.idl"] = "INTERFACES" 498 self.pdata["FILETYPES"]["*.idl"] = "INTERFACES"
484 if self.pdata["PROJECTTYPE"][0] in ["Qt4", "PyQt5", "E4Plugin", "PySide"]: 499 if self.pdata["PROJECTTYPE"][0] in ["Qt4", "PyQt5", "E4Plugin",
500 "PySide"]:
485 self.pdata["FILETYPES"]["*.ui"] = "FORMS" 501 self.pdata["FILETYPES"]["*.ui"] = "FORMS"
486 self.pdata["FILETYPES"]["*.ui.h"] = "FORMS" 502 self.pdata["FILETYPES"]["*.ui.h"] = "FORMS"
487 if self.pdata["PROJECTTYPE"][0] in ["Qt4", "Qt4C", "E4Plugin", 503 if self.pdata["PROJECTTYPE"][0] in ["Qt4", "Qt4C", "E4Plugin",
488 "PyQt5", "PyQt5C", 504 "PyQt5", "PyQt5C",
489 "PySide", "PySideC"]: 505 "PySide", "PySideC"]:
492 "PyQt5", "PyQt5C", 508 "PyQt5", "PyQt5C",
493 "PySide", "PySideC"]: 509 "PySide", "PySideC"]:
494 self.pdata["FILETYPES"]["*.ts"] = "TRANSLATIONS" 510 self.pdata["FILETYPES"]["*.ts"] = "TRANSLATIONS"
495 self.pdata["FILETYPES"]["*.qm"] = "TRANSLATIONS" 511 self.pdata["FILETYPES"]["*.qm"] = "TRANSLATIONS"
496 try: 512 try:
497 if self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"][0]] is not None: 513 if self.__fileTypeCallbacks[
498 ftypes = self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"][0]]() 514 self.pdata["PROJECTTYPE"][0]] is not None:
515 ftypes = \
516 self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"][0]]()
499 self.pdata["FILETYPES"].update(ftypes) 517 self.pdata["FILETYPES"].update(ftypes)
500 except KeyError: 518 except KeyError:
501 pass 519 pass
502 self.setDirty(True) 520 self.setDirty(True)
503 521
504 def updateFileTypes(self): 522 def updateFileTypes(self):
505 """ 523 """
506 Public method to update the filetype associations with new default values. 524 Public method to update the filetype associations with new default
525 values.
507 """ 526 """
508 if self.pdata["PROJECTTYPE"][0] in ["Qt4", "Qt4C", "E4Plugin", 527 if self.pdata["PROJECTTYPE"][0] in ["Qt4", "Qt4C", "E4Plugin",
509 "PyQt5", "PyQt5C", 528 "PyQt5", "PyQt5C",
510 "PySide", "PySideC"]: 529 "PySide", "PySideC"]:
511 if "*.ts" not in self.pdata["FILETYPES"]: 530 if "*.ts" not in self.pdata["FILETYPES"]:
512 self.pdata["FILETYPES"]["*.ts"] = "TRANSLATIONS" 531 self.pdata["FILETYPES"]["*.ts"] = "TRANSLATIONS"
513 if "*.qm" not in self.pdata["FILETYPES"]: 532 if "*.qm" not in self.pdata["FILETYPES"]:
514 self.pdata["FILETYPES"]["*.qm"] = "TRANSLATIONS" 533 self.pdata["FILETYPES"]["*.qm"] = "TRANSLATIONS"
515 try: 534 try:
516 if self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"][0]] is not None: 535 if self.__fileTypeCallbacks[
517 ftypes = self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"][0]]() 536 self.pdata["PROJECTTYPE"][0]] is not None:
537 ftypes = \
538 self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"][0]]()
518 for pattern, ftype in list(ftypes.items()): 539 for pattern, ftype in list(ftypes.items()):
519 if pattern not in self.pdata["FILETYPES"]: 540 if pattern not in self.pdata["FILETYPES"]:
520 self.pdata["FILETYPES"][pattern] = ftype 541 self.pdata["FILETYPES"][pattern] = ftype
521 self.setDirty(True) 542 self.setDirty(True)
522 except KeyError: 543 except KeyError:
649 f.close() 670 f.close()
650 else: 671 else:
651 QApplication.restoreOverrideCursor() 672 QApplication.restoreOverrideCursor()
652 E5MessageBox.critical(self.ui, 673 E5MessageBox.critical(self.ui,
653 self.trUtf8("Read project file"), 674 self.trUtf8("Read project file"),
654 self.trUtf8("<p>The project file <b>{0}</b> could not be read.</p>")\ 675 self.trUtf8(
676 "<p>The project file <b>{0}</b> could not be read.</p>")\
655 .format(fn)) 677 .format(fn))
656 return False 678 return False
657 679
658 self.pfile = os.path.abspath(fn) 680 self.pfile = os.path.abspath(fn)
659 self.ppath = os.path.abspath(os.path.dirname(fn)) 681 self.ppath = os.path.abspath(os.path.dirname(fn))
664 if res: 686 if res:
665 if len(self.pdata["TRANSLATIONPATTERN"]) == 1: 687 if len(self.pdata["TRANSLATIONPATTERN"]) == 1:
666 self.translationsRoot = \ 688 self.translationsRoot = \
667 self.pdata["TRANSLATIONPATTERN"][0].split("%language%")[0] 689 self.pdata["TRANSLATIONPATTERN"][0].split("%language%")[0]
668 elif len(self.pdata["MAINSCRIPT"]) == 1: 690 elif len(self.pdata["MAINSCRIPT"]) == 1:
669 self.translationsRoot = os.path.splitext(self.pdata["MAINSCRIPT"][0])[0] 691 self.translationsRoot = os.path.splitext(
692 self.pdata["MAINSCRIPT"][0])[0]
670 if os.path.isdir(os.path.join(self.ppath, self.translationsRoot)): 693 if os.path.isdir(os.path.join(self.ppath, self.translationsRoot)):
671 dn = self.translationsRoot 694 dn = self.translationsRoot
672 else: 695 else:
673 dn = os.path.dirname(self.translationsRoot) 696 dn = os.path.dirname(self.translationsRoot)
674 if dn not in self.subdirs: 697 if dn not in self.subdirs:
675 self.subdirs.append(dn) 698 self.subdirs.append(dn)
676 699
677 self.name = os.path.splitext(os.path.basename(fn))[0] 700 self.name = os.path.splitext(os.path.basename(fn))[0]
678 701
679 # check, if the files of the project still exist in the project directory 702 # check, if the files of the project still exist in the
703 # project directory
680 self.__checkFilesExist("SOURCES") 704 self.__checkFilesExist("SOURCES")
681 self.__checkFilesExist("FORMS") 705 self.__checkFilesExist("FORMS")
682 self.__checkFilesExist("INTERFACES") 706 self.__checkFilesExist("INTERFACES")
683 self.__checkFilesExist("TRANSLATIONS") 707 self.__checkFilesExist("TRANSLATIONS")
684 self.__checkFilesExist("RESOURCES") 708 self.__checkFilesExist("RESOURCES")
714 def __writeProject(self, fn=None): 738 def __writeProject(self, fn=None):
715 """ 739 """
716 Private method to save the project infos to a project file. 740 Private method to save the project infos to a project file.
717 741
718 @param fn optional filename of the project file to be written (string). 742 @param fn optional filename of the project file to be written (string).
719 If fn is None, the filename stored in the project object 743 If fn is None, the filename stored in the project object
720 is used. This is the 'save' action. If fn is given, this filename 744 is used. This is the 'save' action. If fn is given, this filename
721 is used instead of the one in the project object. This is the 745 is used instead of the one in the project object. This is the
722 'save as' action. 746 'save as' action.
723 @return flag indicating success 747 @return flag indicating success
724 """ 748 """
725 if self.vcs is not None: 749 if self.vcs is not None:
726 self.pdata["VCSOPTIONS"] = [copy.deepcopy(self.vcs.vcsGetOptions())] 750 self.pdata["VCSOPTIONS"] = [
727 self.pdata["VCSOTHERDATA"] = [copy.deepcopy(self.vcs.vcsGetOtherData())] 751 copy.deepcopy(self.vcs.vcsGetOptions())]
752 self.pdata["VCSOTHERDATA"] = [
753 copy.deepcopy(self.vcs.vcsGetOtherData())]
728 754
729 if not self.pdata["HASH"][0]: 755 if not self.pdata["HASH"][0]:
730 hash = str(QCryptographicHash.hash( 756 hash = str(QCryptographicHash.hash(
731 QByteArray(self.ppath.encode("utf-8")), 757 QByteArray(self.ppath.encode("utf-8")),
732 QCryptographicHash.Sha1).toHex(), 758 QCryptographicHash.Sha1).toHex(),
737 fn = self.pfile 763 fn = self.pfile
738 764
739 f = QFile(fn) 765 f = QFile(fn)
740 if f.open(QIODevice.WriteOnly): 766 if f.open(QIODevice.WriteOnly):
741 from E5XML.ProjectWriter import ProjectWriter 767 from E5XML.ProjectWriter import ProjectWriter
742 ProjectWriter(f, os.path.splitext(os.path.basename(fn))[0]).writeXML() 768 ProjectWriter(f, os.path.splitext(
769 os.path.basename(fn))[0]).writeXML()
743 res = True 770 res = True
744 else: 771 else:
745 E5MessageBox.critical(self.ui, 772 E5MessageBox.critical(self.ui,
746 self.trUtf8("Save project file"), 773 self.trUtf8("Save project file"),
747 self.trUtf8("<p>The project file <b>{0}</b> could not be written.</p>")\ 774 self.trUtf8(
748 .format(fn)) 775 "<p>The project file <b>{0}</b> could not be"
776 " written.</p>").format(fn))
749 res = False 777 res = False
750 778
751 if res: 779 if res:
752 self.pfile = os.path.abspath(fn) 780 self.pfile = os.path.abspath(fn)
753 self.ppath = os.path.abspath(os.path.dirname(fn)) 781 self.ppath = os.path.abspath(os.path.dirname(fn))
759 787
760 return res 788 return res
761 789
762 def __readUserProperties(self): 790 def __readUserProperties(self):
763 """ 791 """
764 Private method to read in the user specific project file (.e4q) 792 Private method to read in the user specific project file (.e4q).
765 """ 793 """
766 if self.pfile is None: 794 if self.pfile is None:
767 return 795 return
768 796
769 fn, ext = os.path.splitext(os.path.basename(self.pfile)) 797 fn, ext = os.path.splitext(os.path.basename(self.pfile))
776 reader.readXML() 804 reader.readXML()
777 f.close() 805 f.close()
778 else: 806 else:
779 E5MessageBox.critical(self.ui, 807 E5MessageBox.critical(self.ui,
780 self.trUtf8("Read user project properties"), 808 self.trUtf8("Read user project properties"),
781 self.trUtf8("<p>The user specific project properties file <b>{0}</b>" 809 self.trUtf8(
782 " could not be read.</p>").format(fn)) 810 "<p>The user specific project properties file"
811 " <b>{0}</b> could not be read.</p>").format(fn))
783 812
784 def __writeUserProperties(self): 813 def __writeUserProperties(self):
785 """ 814 """
786 Private method to write the project data to an XML file. 815 Private method to write the project data to an XML file.
787 """ 816 """
792 fn = os.path.join(self.getProjectManagementDir(), '{0}.e4q'.format(fn)) 821 fn = os.path.join(self.getProjectManagementDir(), '{0}.e4q'.format(fn))
793 822
794 f = QFile(fn) 823 f = QFile(fn)
795 if f.open(QIODevice.WriteOnly): 824 if f.open(QIODevice.WriteOnly):
796 from E5XML.UserProjectWriter import UserProjectWriter 825 from E5XML.UserProjectWriter import UserProjectWriter
797 UserProjectWriter(f, os.path.splitext(os.path.basename(fn))[0]).writeXML() 826 UserProjectWriter(
827 f, os.path.splitext(os.path.basename(fn))[0]).writeXML()
798 f.close() 828 f.close()
799 else: 829 else:
800 E5MessageBox.critical(self.ui, 830 E5MessageBox.critical(self.ui,
801 self.trUtf8("Save user project properties"), 831 self.trUtf8("Save user project properties"),
802 self.trUtf8("<p>The user specific project properties file <b>{0}</b>" 832 self.trUtf8(
833 "<p>The user specific project properties file <b>{0}</b>"
803 " could not be written.</p>").format(fn)) 834 " could not be written.</p>").format(fn))
804 835
805 def __showContextMenuSession(self): 836 def __showContextMenuSession(self):
806 """ 837 """
807 Private slot called before the Session menu is shown. 838 Private slot called before the Session menu is shown.
812 else: 843 else:
813 fn, ext = os.path.splitext(os.path.basename(self.pfile)) 844 fn, ext = os.path.splitext(os.path.basename(self.pfile))
814 fn = os.path.join(self.getProjectManagementDir(), 845 fn = os.path.join(self.getProjectManagementDir(),
815 '{0}.e4s'.format(fn)) 846 '{0}.e4s'.format(fn))
816 enable = os.path.exists(fn) 847 enable = os.path.exists(fn)
817 self.sessActGrp.findChild(QAction, "project_load_session").setEnabled(enable) 848 self.sessActGrp.findChild(
818 self.sessActGrp.findChild(QAction, "project_delete_session").setEnabled(enable) 849 QAction, "project_load_session").setEnabled(enable)
850 self.sessActGrp.findChild(
851 QAction, "project_delete_session").setEnabled(enable)
819 852
820 def __readSession(self, quiet=False, indicator=""): 853 def __readSession(self, quiet=False, indicator=""):
821 """ 854 """
822 Private method to read in the project session file (.e4s) 855 Private method to read in the project session file (.e4s).
823 856
824 @param quiet flag indicating quiet operations. 857 @param quiet flag indicating quiet operations.
825 If this flag is true, no errors are reported. 858 If this flag is true, no errors are reported.
826 @keyparam indicator indicator string (string) 859 @keyparam indicator indicator string (string)
827 """ 860 """
844 f.close() 877 f.close()
845 else: 878 else:
846 if not quiet: 879 if not quiet:
847 E5MessageBox.critical(self.ui, 880 E5MessageBox.critical(self.ui,
848 self.trUtf8("Read project session"), 881 self.trUtf8("Read project session"),
849 self.trUtf8("<p>The project session file <b>{0}</b> could not be" 882 self.trUtf8(
883 "<p>The project session file <b>{0}</b> could not be"
850 " read.</p>").format(fn)) 884 " read.</p>").format(fn))
851 885
852 def __writeSession(self, quiet=False, indicator=""): 886 def __writeSession(self, quiet=False, indicator=""):
853 """ 887 """
854 Private method to write the session data to an XML file (.e4s). 888 Private method to write the session data to an XML file (.e4s).
869 '{0}{1}.e4s'.format(fn, indicator)) 903 '{0}{1}.e4s'.format(fn, indicator))
870 904
871 f = QFile(fn) 905 f = QFile(fn)
872 if f.open(QIODevice.WriteOnly): 906 if f.open(QIODevice.WriteOnly):
873 from E5XML.SessionWriter import SessionWriter 907 from E5XML.SessionWriter import SessionWriter
874 SessionWriter(f, os.path.splitext(os.path.basename(fn))[0]).writeXML() 908 SessionWriter(
909 f, os.path.splitext(os.path.basename(fn))[0]).writeXML()
875 f.close() 910 f.close()
876 else: 911 else:
877 if not quiet: 912 if not quiet:
878 E5MessageBox.critical(self.ui, 913 E5MessageBox.critical(self.ui,
879 self.trUtf8("Save project session"), 914 self.trUtf8("Save project session"),
880 self.trUtf8("<p>The project session file <b>{0}</b> could not be" 915 self.trUtf8(
916 "<p>The project session file <b>{0}</b> could not be"
881 " written.</p>").format(fn)) 917 " written.</p>").format(fn))
882 918
883 def __deleteSession(self): 919 def __deleteSession(self):
884 """ 920 """
885 Private method to delete the session file. 921 Private method to delete the session file.
890 self.trUtf8("Please save the project first.")) 926 self.trUtf8("Please save the project first."))
891 return 927 return
892 928
893 fname, ext = os.path.splitext(os.path.basename(self.pfile)) 929 fname, ext = os.path.splitext(os.path.basename(self.pfile))
894 930
895 for fn in [os.path.join(self.getProjectManagementDir(), "{0}.e4s".format(fname))]: 931 for fn in [os.path.join(
932 self.getProjectManagementDir(), "{0}.e4s".format(fname))]:
896 if os.path.exists(fn): 933 if os.path.exists(fn):
897 try: 934 try:
898 os.remove(fn) 935 os.remove(fn)
899 except OSError: 936 except OSError:
900 E5MessageBox.critical(self.ui, 937 E5MessageBox.critical(self.ui,
901 self.trUtf8("Delete project session"), 938 self.trUtf8("Delete project session"),
902 self.trUtf8("<p>The project session file <b>{0}</b> could not be" 939 self.trUtf8(
903 " deleted.</p>").format(fn)) 940 "<p>The project session file <b>{0}</b> could"
941 " not be deleted.</p>").format(fn))
904 942
905 def __readTasks(self): 943 def __readTasks(self):
906 """ 944 """
907 Private method to read in the project tasks file (.e4t) 945 Private method to read in the project tasks file (.e4t).
908 """ 946 """
909 if self.pfile is None: 947 if self.pfile is None:
910 E5MessageBox.critical(self.ui, 948 E5MessageBox.critical(self.ui,
911 self.trUtf8("Read tasks"), 949 self.trUtf8("Read tasks"),
912 self.trUtf8("Please save the project first.")) 950 self.trUtf8("Please save the project first."))
923 reader.readXML() 961 reader.readXML()
924 f.close() 962 f.close()
925 else: 963 else:
926 E5MessageBox.critical(self.ui, 964 E5MessageBox.critical(self.ui,
927 self.trUtf8("Read tasks"), 965 self.trUtf8("Read tasks"),
928 self.trUtf8("<p>The tasks file <b>{0}</b> could not be read.</p>")\ 966 self.trUtf8(
967 "<p>The tasks file <b>{0}</b> could not be read.</p>")\
929 .format(fn)) 968 .format(fn))
930 969
931 def writeTasks(self): 970 def writeTasks(self):
932 """ 971 """
933 Public method to write the tasks data to an XML file (.e4t). 972 Public method to write the tasks data to an XML file (.e4t).
941 f = QFile(fn) 980 f = QFile(fn)
942 ok = f.open(QIODevice.WriteOnly) 981 ok = f.open(QIODevice.WriteOnly)
943 if not ok: 982 if not ok:
944 E5MessageBox.critical(self.ui, 983 E5MessageBox.critical(self.ui,
945 self.trUtf8("Save tasks"), 984 self.trUtf8("Save tasks"),
946 self.trUtf8("<p>The tasks file <b>{0}</b> could not be written.</p>") 985 self.trUtf8(
986 "<p>The tasks file <b>{0}</b> could not be written.</p>")
947 .format(fn)) 987 .format(fn))
948 return 988 return
949 989
950 from E5XML.TasksWriter import TasksWriter 990 from E5XML.TasksWriter import TasksWriter
951 TasksWriter(f, True, os.path.splitext(os.path.basename(fn))[0]).writeXML() 991 TasksWriter(
992 f, True, os.path.splitext(os.path.basename(fn))[0]).writeXML()
952 f.close() 993 f.close()
953 994
954 def __showContextMenuDebugger(self): 995 def __showContextMenuDebugger(self):
955 """ 996 """
956 Private slot called before the Debugger menu is shown. 997 Private slot called before the Debugger menu is shown.
961 else: 1002 else:
962 fn, ext = os.path.splitext(os.path.basename(self.pfile)) 1003 fn, ext = os.path.splitext(os.path.basename(self.pfile))
963 fn = os.path.join(self.getProjectManagementDir(), 1004 fn = os.path.join(self.getProjectManagementDir(),
964 '{0}.e4d'.format(fn)) 1005 '{0}.e4d'.format(fn))
965 enable = os.path.exists(fn) 1006 enable = os.path.exists(fn)
966 self.dbgActGrp.findChild(QAction, "project_debugger_properties_load")\ 1007 self.dbgActGrp.findChild(
967 .setEnabled(enable) 1008 QAction, "project_debugger_properties_load").setEnabled(enable)
968 self.dbgActGrp.findChild(QAction, "project_debugger_properties_delete")\ 1009 self.dbgActGrp.findChild(
969 .setEnabled(enable) 1010 QAction, "project_debugger_properties_delete").setEnabled(enable)
970 1011
971 def __readDebugProperties(self, quiet=False): 1012 def __readDebugProperties(self, quiet=False):
972 """ 1013 """
973 Private method to read in the project debugger properties file (.e4d) 1014 Private method to read in the project debugger properties file (.e4d).
974 1015
975 @param quiet flag indicating quiet operations. 1016 @param quiet flag indicating quiet operations.
976 If this flag is true, no errors are reported. 1017 If this flag is true, no errors are reported.
977 """ 1018 """
978 if self.pfile is None: 1019 if self.pfile is None:
993 f.close() 1034 f.close()
994 else: 1035 else:
995 if not quiet: 1036 if not quiet:
996 E5MessageBox.critical(self.ui, 1037 E5MessageBox.critical(self.ui,
997 self.trUtf8("Read debugger properties"), 1038 self.trUtf8("Read debugger properties"),
998 self.trUtf8("<p>The project debugger properties file <b>{0}</b> could" 1039 self.trUtf8(
999 " not be read.</p>").format(fn)) 1040 "<p>The project debugger properties file <b>{0}</b>"
1041 " could not be read.</p>").format(fn))
1000 1042
1001 def __writeDebugProperties(self, quiet=False): 1043 def __writeDebugProperties(self, quiet=False):
1002 """ 1044 """
1003 Private method to write the project debugger properties file (.e4d) 1045 Private method to write the project debugger properties file (.e4d).
1004 1046
1005 @param quiet flag indicating quiet operations. 1047 @param quiet flag indicating quiet operations.
1006 If this flag is true, no errors are reported. 1048 If this flag is true, no errors are reported.
1007 """ 1049 """
1008 if self.pfile is None: 1050 if self.pfile is None:
1016 fn = os.path.join(self.getProjectManagementDir(), '{0}.e4d'.format(fn)) 1058 fn = os.path.join(self.getProjectManagementDir(), '{0}.e4d'.format(fn))
1017 1059
1018 f = QFile(fn) 1060 f = QFile(fn)
1019 if f.open(QIODevice.WriteOnly): 1061 if f.open(QIODevice.WriteOnly):
1020 from E5XML.DebuggerPropertiesWriter import DebuggerPropertiesWriter 1062 from E5XML.DebuggerPropertiesWriter import DebuggerPropertiesWriter
1021 DebuggerPropertiesWriter(f, os.path.splitext(os.path.basename(fn))[0])\ 1063 DebuggerPropertiesWriter(
1022 .writeXML() 1064 f, os.path.splitext(os.path.basename(fn))[0]).writeXML()
1023 f.close() 1065 f.close()
1024 else: 1066 else:
1025 if not quiet: 1067 if not quiet:
1026 E5MessageBox.critical(self.ui, 1068 E5MessageBox.critical(self.ui,
1027 self.trUtf8("Save debugger properties"), 1069 self.trUtf8("Save debugger properties"),
1028 self.trUtf8("<p>The project debugger properties file <b>{0}</b> could" 1070 self.trUtf8(
1029 " not be written.</p>") 1071 "<p>The project debugger properties file <b>{0}</b>"
1030 .format(fn)) 1072 " could not be written.</p>").format(fn))
1031 1073
1032 def __deleteDebugProperties(self): 1074 def __deleteDebugProperties(self):
1033 """ 1075 """
1034 Private method to delete the project debugger properties file (.e4d) 1076 Private method to delete the project debugger properties file (.e4d).
1035 """ 1077 """
1036 if self.pfile is None: 1078 if self.pfile is None:
1037 E5MessageBox.critical(self.ui, 1079 E5MessageBox.critical(self.ui,
1038 self.trUtf8("Delete debugger properties"), 1080 self.trUtf8("Delete debugger properties"),
1039 self.trUtf8("Please save the project first.")) 1081 self.trUtf8("Please save the project first."))
1040 return 1082 return
1041 1083
1042 fname, ext = os.path.splitext(os.path.basename(self.pfile)) 1084 fname, ext = os.path.splitext(os.path.basename(self.pfile))
1043 1085
1044 for fn in [os.path.join(self.getProjectManagementDir(), "{0}.e4d".format(fname))]: 1086 for fn in [os.path.join(self.getProjectManagementDir(),
1087 "{0}.e4d".format(fname))]:
1045 if os.path.exists(fn): 1088 if os.path.exists(fn):
1046 try: 1089 try:
1047 os.remove(fn) 1090 os.remove(fn)
1048 except OSError: 1091 except OSError:
1049 E5MessageBox.critical(self.ui, 1092 E5MessageBox.critical(self.ui,
1050 self.trUtf8("Delete debugger properties"), 1093 self.trUtf8("Delete debugger properties"),
1051 self.trUtf8("<p>The project debugger properties file <b>{0}</b>" 1094 self.trUtf8(
1052 " could not be deleted.</p>") 1095 "<p>The project debugger properties file"
1096 " <b>{0}</b> could not be deleted.</p>")
1053 .format(fn)) 1097 .format(fn))
1054 1098
1055 def __initDebugProperties(self): 1099 def __initDebugProperties(self):
1056 """ 1100 """
1057 Private method to initialize the debug properties. 1101 Private method to initialize the debug properties.
1106 @param excIgnoreList list of exceptions to be ignored (list of strings) 1150 @param excIgnoreList list of exceptions to be ignored (list of strings)
1107 @param autoClearShell flag indicating, that the interpreter window 1151 @param autoClearShell flag indicating, that the interpreter window
1108 should be cleared (boolean) 1152 should be cleared (boolean)
1109 @keyparam tracePython flag to indicate if the Python library should be 1153 @keyparam tracePython flag to indicate if the Python library should be
1110 traced as well (boolean) 1154 traced as well (boolean)
1111 @keyparam autoContinue flag indicating, that the debugger should not stop 1155 @keyparam autoContinue flag indicating, that the debugger should not
1112 at the first executable line (boolean) 1156 stop at the first executable line (boolean)
1113 """ 1157 """
1114 self.dbgCmdline = argv 1158 self.dbgCmdline = argv
1115 self.dbgWd = wd 1159 self.dbgWd = wd
1116 self.dbgEnv = env 1160 self.dbgEnv = env
1117 self.dbgReportExceptions = excReporting 1161 self.dbgReportExceptions = excReporting
1140 """ 1184 """
1141 if len(self.pdata["TRANSLATIONPATTERN"]) == 0 or \ 1185 if len(self.pdata["TRANSLATIONPATTERN"]) == 0 or \
1142 self.pdata["TRANSLATIONPATTERN"][0] == '': 1186 self.pdata["TRANSLATIONPATTERN"][0] == '':
1143 E5MessageBox.critical(self.ui, 1187 E5MessageBox.critical(self.ui,
1144 self.trUtf8("Add Language"), 1188 self.trUtf8("Add Language"),
1145 self.trUtf8("You have to specify a translation pattern first.")) 1189 self.trUtf8(
1190 "You have to specify a translation pattern first."))
1146 return 1191 return
1147 1192
1148 from .AddLanguageDialog import AddLanguageDialog 1193 from .AddLanguageDialog import AddLanguageDialog
1149 dlg = AddLanguageDialog(self.parent()) 1194 dlg = AddLanguageDialog(self.parent())
1150 if dlg.exec_() == QDialog.Accepted: 1195 if dlg.exec_() == QDialog.Accepted:
1151 lang = dlg.getSelectedLanguage() 1196 lang = dlg.getSelectedLanguage()
1152 if self.pdata["PROJECTTYPE"][0] in \ 1197 if self.pdata["PROJECTTYPE"][0] in \
1153 ["Qt4", "Qt4C", "PyQt5", "PyQt5C", "E4Plugin", "PySide", "PySideC"]: 1198 ["Qt4", "Qt4C", "PyQt5", "PyQt5C", "E4Plugin", "PySide",
1154 langFile = self.pdata["TRANSLATIONPATTERN"][0].replace("%language%", lang) 1199 "PySideC"]:
1200 langFile = self.pdata["TRANSLATIONPATTERN"][0]\
1201 .replace("%language%", lang)
1155 self.appendFile(langFile) 1202 self.appendFile(langFile)
1156 self.projectLanguageAddedByCode.emit(lang) 1203 self.projectLanguageAddedByCode.emit(lang)
1157 1204
1158 def __binaryTranslationFile(self, langFile): 1205 def __binaryTranslationFile(self, langFile):
1159 """ 1206 """
1160 Private method to calculate the filename of the binary translations file 1207 Private method to calculate the filename of the binary translations
1161 given the name of the raw translations file. 1208 file given the name of the raw translations file.
1162 1209
1163 @param langFile name of the raw translations file (string) 1210 @param langFile name of the raw translations file (string)
1164 @return name of the binary translations file (string) 1211 @return name of the binary translations file (string)
1165 """ 1212 """
1166 qmFile = "" 1213 qmFile = ""
1167 try: 1214 try:
1168 if self.__binaryTranslationsCallbacks[self.pdata["PROJECTTYPE"][0]] \ 1215 if self.__binaryTranslationsCallbacks[
1169 is not None: 1216 self.pdata["PROJECTTYPE"][0]] is not None:
1170 qmFile = self.__binaryTranslationsCallbacks[ 1217 qmFile = self.__binaryTranslationsCallbacks[
1171 self.pdata["PROJECTTYPE"][0]](langFile) 1218 self.pdata["PROJECTTYPE"][0]](langFile)
1172 except KeyError: 1219 except KeyError:
1173 qmFile = langFile.replace('.ts', '.qm') 1220 qmFile = langFile.replace('.ts', '.qm')
1174 if qmFile == langFile: 1221 if qmFile == langFile:
1231 if os.path.exists(fn): 1278 if os.path.exists(fn):
1232 os.remove(fn) 1279 os.remove(fn)
1233 except IOError: 1280 except IOError:
1234 E5MessageBox.critical(self.ui, 1281 E5MessageBox.critical(self.ui,
1235 self.trUtf8("Delete translation"), 1282 self.trUtf8("Delete translation"),
1236 self.trUtf8("<p>The selected translation file <b>{0}</b> could not be" 1283 self.trUtf8(
1284 "<p>The selected translation file <b>{0}</b> could not be"
1237 " deleted.</p>").format(langFile)) 1285 " deleted.</p>").format(langFile))
1238 return 1286 return
1239 1287
1240 self.removeLanguageFile(langFile) 1288 self.removeLanguageFile(langFile)
1241 1289
1250 if os.path.exists(fn): 1298 if os.path.exists(fn):
1251 os.remove(fn) 1299 os.remove(fn)
1252 except IOError: 1300 except IOError:
1253 E5MessageBox.critical(self.ui, 1301 E5MessageBox.critical(self.ui,
1254 self.trUtf8("Delete translation"), 1302 self.trUtf8("Delete translation"),
1255 self.trUtf8("<p>The selected translation file <b>{0}</b> could not be" 1303 self.trUtf8(
1256 " deleted.</p>").format(qmFile)) 1304 "<p>The selected translation file <b>{0}</b> could"
1305 " not be deleted.</p>").format(qmFile))
1257 return 1306 return
1258 1307
1259 def appendFile(self, fn, isSourceFile=False, updateModel=True): 1308 def appendFile(self, fn, isSourceFile=False, updateModel=True):
1260 """ 1309 """
1261 Public method to append a file to the project. 1310 Public method to append a file to the project.
1262 1311
1263 @param fn filename to be added to the project (string) 1312 @param fn filename to be added to the project (string)
1264 @param isSourceFile flag indicating that this is a source file 1313 @param isSourceFile flag indicating that this is a source file
1265 even if it doesn't have the source extension (boolean) 1314 even if it doesn't have the source extension (boolean)
1266 @param updateModel flag indicating an update of the model is requested (boolean) 1315 @param updateModel flag indicating an update of the model is
1316 requested (boolean)
1267 """ 1317 """
1268 dirty = False 1318 dirty = False
1269 1319
1270 if os.path.isabs(fn): 1320 if os.path.isabs(fn):
1271 # make it relative to the project root, if it starts with that path 1321 # make it relative to the project root, if it starts with that path
1281 filetype = "OTHERS" 1331 filetype = "OTHERS"
1282 bfn = os.path.basename(newfn) 1332 bfn = os.path.basename(newfn)
1283 if fnmatch.fnmatch(bfn, '*.ts') or fnmatch.fnmatch(bfn, '*.qm'): 1333 if fnmatch.fnmatch(bfn, '*.ts') or fnmatch.fnmatch(bfn, '*.qm'):
1284 filetype = "TRANSLATIONS" 1334 filetype = "TRANSLATIONS"
1285 else: 1335 else:
1286 for pattern in reversed(sorted(self.pdata["FILETYPES"].keys())): 1336 for pattern in reversed(
1337 sorted(self.pdata["FILETYPES"].keys())):
1287 if fnmatch.fnmatch(bfn, pattern): 1338 if fnmatch.fnmatch(bfn, pattern):
1288 filetype = self.pdata["FILETYPES"][pattern] 1339 filetype = self.pdata["FILETYPES"][pattern]
1289 break 1340 break
1290 1341
1291 if filetype == "__IGNORE__": 1342 if filetype == "__IGNORE__":
1310 updateModel and self.repopulateItem(newfn) 1361 updateModel and self.repopulateItem(newfn)
1311 elif filetype == "INTERFACES": 1362 elif filetype == "INTERFACES":
1312 if newfn not in self.pdata["INTERFACES"]: 1363 if newfn not in self.pdata["INTERFACES"]:
1313 self.pdata["INTERFACES"].append(newfn) 1364 self.pdata["INTERFACES"].append(newfn)
1314 self.projectInterfaceAdded.emit(newfn) 1365 self.projectInterfaceAdded.emit(newfn)
1315 updateModel and self.__model.addNewItem("INTERFACES", newfn) 1366 updateModel and \
1367 self.__model.addNewItem("INTERFACES", newfn)
1316 dirty = True 1368 dirty = True
1317 else: 1369 else:
1318 updateModel and self.repopulateItem(newfn) 1370 updateModel and self.repopulateItem(newfn)
1319 elif filetype == "RESOURCES": 1371 elif filetype == "RESOURCES":
1320 if newfn not in self.pdata["RESOURCES"]: 1372 if newfn not in self.pdata["RESOURCES"]:
1370 os.makedirs(target) 1422 os.makedirs(target)
1371 1423
1372 if os.path.exists(targetfile): 1424 if os.path.exists(targetfile):
1373 res = E5MessageBox.yesNo(self.ui, 1425 res = E5MessageBox.yesNo(self.ui,
1374 self.trUtf8("Add file"), 1426 self.trUtf8("Add file"),
1375 self.trUtf8("<p>The file <b>{0}</b> already" 1427 self.trUtf8(
1428 "<p>The file <b>{0}</b> already"
1376 " exists.</p><p>Overwrite it?</p>") 1429 " exists.</p><p>Overwrite it?</p>")
1377 .format(targetfile), 1430 .format(targetfile),
1378 icon=E5MessageBox.Warning) 1431 icon=E5MessageBox.Warning)
1379 if not res: 1432 if not res:
1380 return # don't overwrite 1433 return # don't overwrite
1381 1434
1382 shutil.copy(fn, target) 1435 shutil.copy(fn, target)
1383 except IOError as why: 1436 except IOError as why:
1384 E5MessageBox.critical(self.ui, 1437 E5MessageBox.critical(self.ui,
1385 self.trUtf8("Add file"), 1438 self.trUtf8("Add file"),
1386 self.trUtf8("<p>The selected file <b>{0}</b> could not be" 1439 self.trUtf8(
1387 " added to <b>{1}</b>.</p><p>Reason: {2}</p>") 1440 "<p>The selected file <b>{0}</b> could"
1441 " not be added to <b>{1}</b>.</p>"
1442 "<p>Reason: {2}</p>")
1388 .format(fn, target, str(why))) 1443 .format(fn, target, str(why)))
1389 continue 1444 continue
1390 1445
1391 self.appendFile(targetfile, isSource or filter == 'source') 1446 self.appendFile(targetfile, isSource or filter == 'source')
1392 else: 1447 else:
1394 self.trUtf8("Add file"), 1449 self.trUtf8("Add file"),
1395 self.trUtf8("The target directory must not be empty.")) 1450 self.trUtf8("The target directory must not be empty."))
1396 1451
1397 def __addSingleDirectory(self, filetype, source, target, quiet=False): 1452 def __addSingleDirectory(self, filetype, source, target, quiet=False):
1398 """ 1453 """
1399 Private method used to add all files of a single directory to the project. 1454 Private method used to add all files of a single directory to the
1455 project.
1400 1456
1401 @param filetype type of files to add (string) 1457 @param filetype type of files to add (string)
1402 @param source source directory (string) 1458 @param source source directory (string)
1403 @param target target directory (string) 1459 @param target target directory (string)
1404 @param quiet flag indicating quiet operations (boolean) 1460 @param quiet flag indicating quiet operations (boolean)
1423 self.trUtf8("Add directory"), 1479 self.trUtf8("Add directory"),
1424 self.trUtf8("<p>The source directory doesn't contain" 1480 self.trUtf8("<p>The source directory doesn't contain"
1425 " any files belonging to the selected category.</p>")) 1481 " any files belonging to the selected category.</p>"))
1426 return 1482 return
1427 1483
1428 if not Utilities.samepath(target, source) and not os.path.isdir(target): 1484 if not Utilities.samepath(target, source) and \
1485 not os.path.isdir(target):
1429 try: 1486 try:
1430 os.makedirs(target) 1487 os.makedirs(target)
1431 except IOError as why: 1488 except IOError as why:
1432 E5MessageBox.critical(self.ui, 1489 E5MessageBox.critical(self.ui,
1433 self.trUtf8("Add directory"), 1490 self.trUtf8("Add directory"),
1434 self.trUtf8("<p>The target directory <b>{0}</b> could not be" 1491 self.trUtf8(
1492 "<p>The target directory <b>{0}</b> could not be"
1435 " created.</p><p>Reason: {1}</p>") 1493 " created.</p><p>Reason: {1}</p>")
1436 .format(target, str(why))) 1494 .format(target, str(why)))
1437 return 1495 return
1438 1496
1439 for file in files: 1497 for file in files:
1445 if not Utilities.samepath(target, source): 1503 if not Utilities.samepath(target, source):
1446 try: 1504 try:
1447 if os.path.exists(targetfile): 1505 if os.path.exists(targetfile):
1448 res = E5MessageBox.yesNo(self.ui, 1506 res = E5MessageBox.yesNo(self.ui,
1449 self.trUtf8("Add directory"), 1507 self.trUtf8("Add directory"),
1450 self.trUtf8("<p>The file <b>{0}</b> already exists.</p>" 1508 self.trUtf8(
1451 "<p>Overwrite it?</p>") 1509 "<p>The file <b>{0}</b> already exists.</p>"
1510 "<p>Overwrite it?</p>")
1452 .format(targetfile), 1511 .format(targetfile),
1453 icon=E5MessageBox.Warning) 1512 icon=E5MessageBox.Warning)
1454 if not res: 1513 if not res:
1455 continue # don't overwrite, carry on with next file 1514 continue # don't overwrite, carry on
1515 # with next file
1456 1516
1457 shutil.copy(file, target) 1517 shutil.copy(file, target)
1458 except EnvironmentError: 1518 except EnvironmentError:
1459 continue 1519 continue
1460 self.appendFile(targetfile) 1520 self.appendFile(targetfile)
1489 @param startdir start directory for the selection dialog (string) 1549 @param startdir start directory for the selection dialog (string)
1490 """ 1550 """
1491 if startdir is None: 1551 if startdir is None:
1492 startdir = self.ppath 1552 startdir = self.ppath
1493 from .AddDirectoryDialog import AddDirectoryDialog 1553 from .AddDirectoryDialog import AddDirectoryDialog
1494 dlg = AddDirectoryDialog(self, filter, self.parent(), startdir=startdir) 1554 dlg = AddDirectoryDialog(
1555 self, filter, self.parent(), startdir=startdir)
1495 if dlg.exec_() == QDialog.Accepted: 1556 if dlg.exec_() == QDialog.Accepted:
1496 filetype, source, target, recursive = dlg.getData() 1557 filetype, source, target, recursive = dlg.getData()
1497 if target == '': 1558 if target == '':
1498 E5MessageBox.critical(self.ui, 1559 E5MessageBox.critical(self.ui,
1499 self.trUtf8("Add directory"), 1560 self.trUtf8("Add directory"),
1567 """ 1628 """
1568 self.addFiles('others') 1629 self.addFiles('others')
1569 1630
1570 def addSourceDir(self): 1631 def addSourceDir(self):
1571 """ 1632 """
1572 Public slot to add all source files of a directory to the current project. 1633 Public slot to add all source files of a directory to the current
1634 project.
1573 """ 1635 """
1574 self.addDirectory('source') 1636 self.addDirectory('source')
1575 1637
1576 def addUiDir(self): 1638 def addUiDir(self):
1577 """ 1639 """
1579 """ 1641 """
1580 self.addDirectory('form') 1642 self.addDirectory('form')
1581 1643
1582 def addIdlDir(self): 1644 def addIdlDir(self):
1583 """ 1645 """
1584 Public slot to add all IDL interfaces of a directory to the current project. 1646 Public slot to add all IDL interfaces of a directory to the current
1647 project.
1585 """ 1648 """
1586 self.addDirectory('interface') 1649 self.addDirectory('interface')
1587 1650
1588 def addResourceDir(self): 1651 def addResourceDir(self):
1589 """ 1652 """
1590 Public slot to add all Qt resource files of a directory to the current project. 1653 Public slot to add all Qt resource files of a directory to the current
1654 project.
1591 """ 1655 """
1592 self.addDirectory('resource') 1656 self.addDirectory('resource')
1593 1657
1594 def addOthersDir(self): 1658 def addOthersDir(self):
1595 """ 1659 """
1648 try: 1712 try:
1649 os.rename(oldfn, newfn) 1713 os.rename(oldfn, newfn)
1650 except OSError as msg: 1714 except OSError as msg:
1651 E5MessageBox.critical(self.ui, 1715 E5MessageBox.critical(self.ui,
1652 self.trUtf8("Rename File"), 1716 self.trUtf8("Rename File"),
1653 self.trUtf8("""<p>The file <b>{0}</b> could not be renamed.<br />""" 1717 self.trUtf8(
1718 """<p>The file <b>{0}</b> could not be renamed.<br />"""
1654 """Reason: {1}</p>""").format(oldfn, str(msg))) 1719 """Reason: {1}</p>""").format(oldfn, str(msg)))
1655 return False 1720 return False
1656 1721
1657 if fn in self.pdata["SOURCES"] or \ 1722 if fn in self.pdata["SOURCES"] or \
1658 fn in self.pdata["FORMS"] or \ 1723 fn in self.pdata["FORMS"] or \
1688 def getFiles(self, start): 1753 def getFiles(self, start):
1689 """ 1754 """
1690 Public method to get all files starting with a common prefix. 1755 Public method to get all files starting with a common prefix.
1691 1756
1692 @param start prefix (string) 1757 @param start prefix (string)
1758 @return list of files starting with a common prefix (list of strings)
1693 """ 1759 """
1694 filelist = [] 1760 filelist = []
1695 start = self.getRelativePath(start) 1761 start = self.getRelativePath(start)
1696 for key in ["SOURCES", "FORMS", "INTERFACES", "RESOURCES", "OTHERS"]: 1762 for key in ["SOURCES", "FORMS", "INTERFACES", "RESOURCES", "OTHERS"]:
1697 for entry in self.pdata[key][:]: 1763 for entry in self.pdata[key][:]:
1710 newdn = self.getRelativePath(newdn) 1776 newdn = self.getRelativePath(newdn)
1711 for key in ["SOURCES", "FORMS", "INTERFACES", "RESOURCES", "OTHERS"]: 1777 for key in ["SOURCES", "FORMS", "INTERFACES", "RESOURCES", "OTHERS"]:
1712 for entry in self.pdata[key][:]: 1778 for entry in self.pdata[key][:]:
1713 if entry.startswith(olddn): 1779 if entry.startswith(olddn):
1714 entry = entry.replace(olddn, newdn) 1780 entry = entry.replace(olddn, newdn)
1715 self.appendFile(os.path.join(self.ppath, entry), key == "SOURCES") 1781 self.appendFile(os.path.join(self.ppath, entry),
1782 key == "SOURCES")
1716 self.setDirty(True) 1783 self.setDirty(True)
1717 1784
1718 def moveDirectory(self, olddn, newdn): 1785 def moveDirectory(self, olddn, newdn):
1719 """ 1786 """
1720 Public slot to move a directory. 1787 Public slot to move a directory.
1751 Public slot to remove a file from the project. 1818 Public slot to remove a file from the project.
1752 1819
1753 The file is not deleted from the project directory. 1820 The file is not deleted from the project directory.
1754 1821
1755 @param fn filename to be removed from the project 1822 @param fn filename to be removed from the project
1756 @param updateModel flag indicating an update of the model is requested (boolean) 1823 @param updateModel flag indicating an update of the model is
1824 requested (boolean)
1757 """ 1825 """
1758 fn = self.getRelativePath(fn) 1826 fn = self.getRelativePath(fn)
1759 dirty = True 1827 dirty = True
1760 if fn in self.pdata["SOURCES"]: 1828 if fn in self.pdata["SOURCES"]:
1761 self.pdata["SOURCES"].remove(fn) 1829 self.pdata["SOURCES"].remove(fn)
1797 dirty = True 1865 dirty = True
1798 if not dn.endswith(os.sep): 1866 if not dn.endswith(os.sep):
1799 dn2 = dn + os.sep 1867 dn2 = dn + os.sep
1800 else: 1868 else:
1801 dn2 = dn 1869 dn2 = dn
1802 for key in ["SOURCES", "FORMS", "INTERFACES", "RESOURCES", "TRANSLATIONS", ]: 1870 for key in ["SOURCES", "FORMS", "INTERFACES", "RESOURCES",
1871 "TRANSLATIONS", ]:
1803 for entry in self.pdata[key][:]: 1872 for entry in self.pdata[key][:]:
1804 if entry.startswith(dn2): 1873 if entry.startswith(dn2):
1805 self.pdata[key].remove(entry) 1874 self.pdata[key].remove(entry)
1806 dirty = True 1875 dirty = True
1807 self.__model.removeItem(dn) 1876 self.__model.removeItem(dn)
1827 for ext in ['.pyc', '.pyo']: 1896 for ext in ['.pyc', '.pyo']:
1828 fn2 = os.path.join(self.ppath, path + ext) 1897 fn2 = os.path.join(self.ppath, path + ext)
1829 if os.path.isfile(fn2): 1898 if os.path.isfile(fn2):
1830 os.remove(fn2) 1899 os.remove(fn2)
1831 pat = os.path.join( 1900 pat = os.path.join(
1832 self.ppath, head, "__pycache__", "{0}.*{1}".format(tail, ext)) 1901 self.ppath, head,
1902 "__pycache__", "{0}.*{1}".format(tail, ext))
1833 for f in glob.glob(pat): 1903 for f in glob.glob(pat):
1834 os.remove(f) 1904 os.remove(f)
1835 except EnvironmentError: 1905 except EnvironmentError:
1836 E5MessageBox.critical(self.ui, 1906 E5MessageBox.critical(self.ui,
1837 self.trUtf8("Delete file"), 1907 self.trUtf8("Delete file"),
1838 self.trUtf8("<p>The selected file <b>{0}</b> could not be deleted.</p>") 1908 self.trUtf8(
1839 .format(fn)) 1909 "<p>The selected file <b>{0}</b> could not be"
1910 " deleted.</p>").format(fn))
1840 return False 1911 return False
1841 1912
1842 self.removeFile(fn) 1913 self.removeFile(fn)
1843 if ext == '.ui': 1914 if ext == '.ui':
1844 self.removeFile(fn + '.h') 1915 self.removeFile(fn + '.h')
1916 self.menuCheckAct.setEnabled(True) 1987 self.menuCheckAct.setEnabled(True)
1917 self.menuShowAct.setEnabled(True) 1988 self.menuShowAct.setEnabled(True)
1918 self.menuDiagramAct.setEnabled(True) 1989 self.menuDiagramAct.setEnabled(True)
1919 self.menuApidocAct.setEnabled(True) 1990 self.menuApidocAct.setEnabled(True)
1920 self.menuPackagersAct.setEnabled(True) 1991 self.menuPackagersAct.setEnabled(True)
1921 self.pluginGrp.setEnabled(self.pdata["PROJECTTYPE"][0] == "E4Plugin") 1992 self.pluginGrp.setEnabled(
1993 self.pdata["PROJECTTYPE"][0] == "E4Plugin")
1922 self.addLanguageAct.setEnabled( 1994 self.addLanguageAct.setEnabled(
1923 len(self.pdata["TRANSLATIONPATTERN"]) > 0 and \ 1995 len(self.pdata["TRANSLATIONPATTERN"]) > 0 and \
1924 self.pdata["TRANSLATIONPATTERN"][0] != '') 1996 self.pdata["TRANSLATIONPATTERN"][0] != '')
1925 1997
1926 self.projectAboutToBeCreated.emit() 1998 self.projectAboutToBeCreated.emit()
1927 1999
1928 hash = str(QCryptographicHash.hash( 2000 hash = str(QCryptographicHash.hash(
1929 QByteArray(self.ppath.encode("utf-8")), QCryptographicHash.Sha1).toHex(), 2001 QByteArray(self.ppath.encode("utf-8")),
2002 QCryptographicHash.Sha1).toHex(),
1930 encoding="utf-8") 2003 encoding="utf-8")
1931 self.pdata["HASH"] = [hash] 2004 self.pdata["HASH"] = [hash]
1932 2005
1933 # create the project directory if it doesn't exist already 2006 # create the project directory if it doesn't exist already
1934 if not os.path.isdir(self.ppath): 2007 if not os.path.isdir(self.ppath):
1935 try: 2008 try:
1936 os.makedirs(self.ppath) 2009 os.makedirs(self.ppath)
1937 except EnvironmentError: 2010 except EnvironmentError:
1938 E5MessageBox.critical(self.ui, 2011 E5MessageBox.critical(self.ui,
1939 self.trUtf8("Create project directory"), 2012 self.trUtf8("Create project directory"),
1940 self.trUtf8("<p>The project directory <b>{0}</b> could not" 2013 self.trUtf8(
2014 "<p>The project directory <b>{0}</b> could not"
1941 " be created.</p>") 2015 " be created.</p>")
1942 .format(self.ppath)) 2016 .format(self.ppath))
1943 self.vcs = self.initVCS() 2017 self.vcs = self.initVCS()
1944 return 2018 return
1945 # create an empty __init__.py file to make it a Python package 2019 # create an empty __init__.py file to make it a Python package
1946 # (only for Python and Python3) 2020 # (only for Python and Python3)
1947 if self.pdata["PROGLANGUAGE"][0] in ["Python", "Python2", "Python3"]: 2021 if self.pdata["PROGLANGUAGE"][0] in \
2022 ["Python", "Python2", "Python3"]:
1948 fn = os.path.join(self.ppath, "__init__.py") 2023 fn = os.path.join(self.ppath, "__init__.py")
1949 f = open(fn, "w", encoding="utf-8") 2024 f = open(fn, "w", encoding="utf-8")
1950 f.close() 2025 f.close()
1951 self.appendFile(fn, True) 2026 self.appendFile(fn, True)
1952 # create an empty main script file, if a name was given 2027 # create an empty main script file, if a name was given
1953 if len(self.pdata["MAINSCRIPT"]) and self.pdata["MAINSCRIPT"][0]: 2028 if len(self.pdata["MAINSCRIPT"]) and \
2029 self.pdata["MAINSCRIPT"][0]:
1954 if not os.path.isabs(self.pdata["MAINSCRIPT"][0]): 2030 if not os.path.isabs(self.pdata["MAINSCRIPT"][0]):
1955 ms = os.path.join(self.ppath, self.pdata["MAINSCRIPT"][0]) 2031 ms = os.path.join(
2032 self.ppath, self.pdata["MAINSCRIPT"][0])
1956 else: 2033 else:
1957 ms = self.pdata["MAINSCRIPT"][0] 2034 ms = self.pdata["MAINSCRIPT"][0]
1958 f = open(ms, "w") 2035 f = open(ms, "w")
1959 f.close() 2036 f.close()
1960 self.appendFile(ms, True) 2037 self.appendFile(ms, True)
1962 if not self.translationsRoot.endswith(os.sep): 2039 if not self.translationsRoot.endswith(os.sep):
1963 tpd = os.path.dirname(tpd) 2040 tpd = os.path.dirname(tpd)
1964 if not os.path.isdir(tpd): 2041 if not os.path.isdir(tpd):
1965 os.makedirs(tpd) 2042 os.makedirs(tpd)
1966 if self.pdata["TRANSLATIONSBINPATH"]: 2043 if self.pdata["TRANSLATIONSBINPATH"]:
1967 tpd = os.path.join(self.ppath, self.pdata["TRANSLATIONSBINPATH"][0]) 2044 tpd = os.path.join(
2045 self.ppath, self.pdata["TRANSLATIONSBINPATH"][0])
1968 if not os.path.isdir(tpd): 2046 if not os.path.isdir(tpd):
1969 os.makedirs(tpd) 2047 os.makedirs(tpd)
1970 2048
1971 # create management directory if not present 2049 # create management directory if not present
1972 mgmtDir = self.getProjectManagementDir() 2050 mgmtDir = self.getProjectManagementDir()
1987 f = open(ms, "w") 2065 f = open(ms, "w")
1988 f.close() 2066 f.close()
1989 except IOError as err: 2067 except IOError as err:
1990 E5MessageBox.critical(self.ui, 2068 E5MessageBox.critical(self.ui,
1991 self.trUtf8("Create main script"), 2069 self.trUtf8("Create main script"),
1992 self.trUtf8("<p>The mainscript <b>{0}</b> could not" 2070 self.trUtf8(
2071 "<p>The mainscript <b>{0}</b> could not"
1993 " be created.<br/>Reason: {1}</p>") 2072 " be created.<br/>Reason: {1}</p>")
1994 .format(self.ppath, str(err))) 2073 .format(self.ppath, str(err)))
1995 self.appendFile(ms) 2074 self.appendFile(ms)
1996 except IndexError: 2075 except IndexError:
1997 ms = "" 2076 ms = ""
2003 yesDefault=True) 2082 yesDefault=True)
2004 if res: 2083 if res:
2005 self.newProjectAddFiles(ms) 2084 self.newProjectAddFiles(ms)
2006 # create an empty __init__.py file to make it a Python package 2085 # create an empty __init__.py file to make it a Python package
2007 # if none exists (only for Python and Python3) 2086 # if none exists (only for Python and Python3)
2008 if self.pdata["PROGLANGUAGE"][0] in ["Python", "Python2", "Python3"]: 2087 if self.pdata["PROGLANGUAGE"][0] in \
2088 ["Python", "Python2", "Python3"]:
2009 fn = os.path.join(self.ppath, "__init__.py") 2089 fn = os.path.join(self.ppath, "__init__.py")
2010 if not os.path.exists(fn): 2090 if not os.path.exists(fn):
2011 f = open(fn, "w", encoding="utf-8") 2091 f = open(fn, "w", encoding="utf-8")
2012 f.close() 2092 f.close()
2013 self.appendFile(fn, True) 2093 self.appendFile(fn, True)
2045 self.setDirty(True) 2125 self.setDirty(True)
2046 if self.vcs is not None: 2126 if self.vcs is not None:
2047 # edit VCS command options 2127 # edit VCS command options
2048 vcores = E5MessageBox.yesNo(self.ui, 2128 vcores = E5MessageBox.yesNo(self.ui,
2049 self.trUtf8("New Project"), 2129 self.trUtf8("New Project"),
2050 self.trUtf8("""Would you like to edit the VCS""" 2130 self.trUtf8(
2131 """Would you like to edit the VCS"""
2051 """ command options?""")) 2132 """ command options?"""))
2052 if vcores: 2133 if vcores:
2053 from VCS.CommandOptionsDialog import \ 2134 from VCS.CommandOptionsDialog import \
2054 vcsCommandOptionsDialog 2135 vcsCommandOptionsDialog
2055 codlg = vcsCommandOptionsDialog(self.vcs) 2136 codlg = vcsCommandOptionsDialog(self.vcs)
2057 self.vcs.vcsSetOptions(codlg.getOptions()) 2138 self.vcs.vcsSetOptions(codlg.getOptions())
2058 # add project file to repository 2139 # add project file to repository
2059 if res == 0: 2140 if res == 0:
2060 apres = E5MessageBox.yesNo(self.ui, 2141 apres = E5MessageBox.yesNo(self.ui,
2061 self.trUtf8("New project"), 2142 self.trUtf8("New project"),
2062 self.trUtf8("Shall the project file be added" 2143 self.trUtf8(
2144 "Shall the project file be added"
2063 " to the repository?"), 2145 " to the repository?"),
2064 yesDefault=True) 2146 yesDefault=True)
2065 if apres: 2147 if apres:
2066 self.saveProject() 2148 self.saveProject()
2067 self.vcs.vcsAdd(self.pfile) 2149 self.vcs.vcsAdd(self.pfile)
2069 self.pdata["VCS"] = ['None'] 2151 self.pdata["VCS"] = ['None']
2070 self.saveProject() 2152 self.saveProject()
2071 break 2153 break
2072 2154
2073 # put the project under VCS control 2155 # put the project under VCS control
2074 if self.vcs is None and self.vcsSoftwareAvailable() and self.vcsRequested: 2156 if self.vcs is None and self.vcsSoftwareAvailable() and \
2157 self.vcsRequested:
2075 vcsSystemsDict = e5App().getObject("PluginManager")\ 2158 vcsSystemsDict = e5App().getObject("PluginManager")\
2076 .getPluginDisplayStrings("version_control") 2159 .getPluginDisplayStrings("version_control")
2077 vcsSystemsDisplay = [self.trUtf8("None")] 2160 vcsSystemsDisplay = [self.trUtf8("None")]
2078 keys = sorted(vcsSystemsDict.keys()) 2161 keys = sorted(vcsSystemsDict.keys())
2079 for key in keys: 2162 for key in keys:
2080 vcsSystemsDisplay.append(vcsSystemsDict[key]) 2163 vcsSystemsDisplay.append(vcsSystemsDict[key])
2081 vcsSelected, ok = QInputDialog.getItem( 2164 vcsSelected, ok = QInputDialog.getItem(
2082 None, 2165 None,
2083 self.trUtf8("New Project"), 2166 self.trUtf8("New Project"),
2084 self.trUtf8("Select version control system for the project"), 2167 self.trUtf8(
2168 "Select version control system for the project"),
2085 vcsSystemsDisplay, 2169 vcsSystemsDisplay,
2086 0, False) 2170 0, False)
2087 if ok and vcsSelected != self.trUtf8("None"): 2171 if ok and vcsSelected != self.trUtf8("None"):
2088 for vcsSystem, vcsSystemDisplay in list(vcsSystemsDict.items()): 2172 for vcsSystem, vcsSystemDisplay in vcsSystemsDict.items():
2089 if vcsSystemDisplay == vcsSelected: 2173 if vcsSystemDisplay == vcsSelected:
2090 break 2174 break
2091 else: 2175 else:
2092 vcsSystem = "None" 2176 vcsSystem = "None"
2093 self.pdata["VCS"] = [vcsSystem] 2177 self.pdata["VCS"] = [vcsSystem]
2104 self.setDirty(True) 2188 self.setDirty(True)
2105 if self.vcs is not None: 2189 if self.vcs is not None:
2106 # edit VCS command options 2190 # edit VCS command options
2107 vcores = E5MessageBox.yesNo(self.ui, 2191 vcores = E5MessageBox.yesNo(self.ui,
2108 self.trUtf8("New Project"), 2192 self.trUtf8("New Project"),
2109 self.trUtf8("""Would you like to edit the VCS command""" 2193 self.trUtf8(
2110 """ options?""")) 2194 """Would you like to edit the VCS command"""
2195 """ options?"""))
2111 if vcores: 2196 if vcores:
2112 codlg = vcsCommandOptionsDialog(self.vcs) 2197 codlg = vcsCommandOptionsDialog(self.vcs)
2113 if codlg.exec_() == QDialog.Accepted: 2198 if codlg.exec_() == QDialog.Accepted:
2114 self.vcs.vcsSetOptions(codlg.getOptions()) 2199 self.vcs.vcsSetOptions(codlg.getOptions())
2115 2200
2152 if self.pdata["TRANSLATIONPATTERN"]: 2237 if self.pdata["TRANSLATIONPATTERN"]:
2153 pattern = os.path.basename(self.pdata["TRANSLATIONPATTERN"][0]) 2238 pattern = os.path.basename(self.pdata["TRANSLATIONPATTERN"][0])
2154 if "%language%" in pattern: 2239 if "%language%" in pattern:
2155 pattern = pattern.replace("%language%", "*") 2240 pattern = pattern.replace("%language%", "*")
2156 else: 2241 else:
2157 tpd = self.pdata["TRANSLATIONPATTERN"][0].split("%language%")[0] 2242 tpd = self.pdata["TRANSLATIONPATTERN"][0].split(
2243 "%language%")[0]
2158 else: 2244 else:
2159 pattern = "*.ts" 2245 pattern = "*.ts"
2160 tslist.extend(Utilities.direntries(tpd, True, pattern)) 2246 tslist.extend(Utilities.direntries(tpd, True, pattern))
2161 pattern = self.__binaryTranslationFile(pattern) 2247 pattern = self.__binaryTranslationFile(pattern)
2162 if pattern: 2248 if pattern:
2166 # the first entry determines the mainscript name 2252 # the first entry determines the mainscript name
2167 mainscriptname = os.path.splitext(mainscript)[0] or \ 2253 mainscriptname = os.path.splitext(mainscript)[0] or \
2168 os.path.basename(tslist[0]).split('_')[0] 2254 os.path.basename(tslist[0]).split('_')[0]
2169 self.pdata["TRANSLATIONPATTERN"] = \ 2255 self.pdata["TRANSLATIONPATTERN"] = \
2170 [os.path.join(os.path.dirname(tslist[0]), 2256 [os.path.join(os.path.dirname(tslist[0]),
2171 "{0}_%language%{1}".format(os.path.basename(tslist[0]).split('_')[0], 2257 "{0}_%language%{1}".format(
2258 os.path.basename(tslist[0]).split('_')[0],
2172 os.path.splitext(tslist[0])[1]))] 2259 os.path.splitext(tslist[0])[1]))]
2173 else: 2260 else:
2174 pattern, ok = QInputDialog.getText( 2261 pattern, ok = QInputDialog.getText(
2175 None, 2262 None,
2176 self.trUtf8("Translation Pattern"), 2263 self.trUtf8("Translation Pattern"),
2177 self.trUtf8("Enter the path pattern for translation files " 2264 self.trUtf8(
2178 "(use '%language%' in place of the language code):"), 2265 "Enter the path pattern for translation files "
2266 "(use '%language%' in place of the language code):"),
2179 QLineEdit.Normal, 2267 QLineEdit.Normal,
2180 tslist[0]) 2268 tslist[0])
2181 if pattern: 2269 if pattern:
2182 self.pdata["TRANSLATIONPATTERN"] = [pattern] 2270 self.pdata["TRANSLATIONPATTERN"] = [pattern]
2183 if self.pdata["TRANSLATIONPATTERN"]: 2271 if self.pdata["TRANSLATIONPATTERN"]:
2184 self.pdata["TRANSLATIONPATTERN"][0] = \ 2272 self.pdata["TRANSLATIONPATTERN"][0] = \
2185 self.getRelativePath(self.pdata["TRANSLATIONPATTERN"][0]) 2273 self.getRelativePath(self.pdata["TRANSLATIONPATTERN"][0])
2186 pattern = self.pdata["TRANSLATIONPATTERN"][0].replace("%language%", "*") 2274 pattern = self.pdata["TRANSLATIONPATTERN"][0]\
2275 .replace("%language%", "*")
2187 for ts in tslist: 2276 for ts in tslist:
2188 if fnmatch.fnmatch(ts, pattern): 2277 if fnmatch.fnmatch(ts, pattern):
2189 self.pdata["TRANSLATIONS"].append(ts) 2278 self.pdata["TRANSLATIONS"].append(ts)
2190 self.projectLanguageAdded.emit(ts) 2279 self.projectLanguageAdded.emit(ts)
2191 if self.pdata["TRANSLATIONSBINPATH"]: 2280 if self.pdata["TRANSLATIONSBINPATH"]:
2192 tpd = os.path.join(self.ppath, 2281 tpd = os.path.join(self.ppath,
2193 self.pdata["TRANSLATIONSBINPATH"][0]) 2282 self.pdata["TRANSLATIONSBINPATH"][0])
2194 pattern = os.path.basename(self.pdata["TRANSLATIONPATTERN"][0])\ 2283 pattern = os.path.basename(
2284 self.pdata["TRANSLATIONPATTERN"][0])\
2195 .replace("%language%", "*") 2285 .replace("%language%", "*")
2196 pattern = self.__binaryTranslationFile(pattern) 2286 pattern = self.__binaryTranslationFile(pattern)
2197 qmlist = Utilities.direntries(tpd, True, pattern) 2287 qmlist = Utilities.direntries(tpd, True, pattern)
2198 for qm in qmlist: 2288 for qm in qmlist:
2199 self.pdata["TRANSLATIONS"].append(qm) 2289 self.pdata["TRANSLATIONS"].append(qm)
2200 self.projectLanguageAdded.emit(qm) 2290 self.projectLanguageAdded.emit(qm)
2201 if len(self.pdata["MAINSCRIPT"]) == 0 or \ 2291 if len(self.pdata["MAINSCRIPT"]) == 0 or \
2202 len(self.pdata["MAINSCRIPT"][0]) == 0: 2292 len(self.pdata["MAINSCRIPT"][0]) == 0:
2203 if self.pdata["PROGLANGUAGE"][0] in ["Python", "Python2", "Python3"]: 2293 if self.pdata["PROGLANGUAGE"][0] in \
2204 self.pdata["MAINSCRIPT"] = ['{0}.py'.format(mainscriptname)] 2294 ["Python", "Python2", "Python3"]:
2295 self.pdata["MAINSCRIPT"] = [
2296 '{0}.py'.format(mainscriptname)]
2205 elif self.pdata["PROGLANGUAGE"][0] == "Ruby": 2297 elif self.pdata["PROGLANGUAGE"][0] == "Ruby":
2206 self.pdata["MAINSCRIPT"] = ['{0}.rb'.format(mainscriptname)] 2298 self.pdata["MAINSCRIPT"] = [
2299 '{0}.rb'.format(mainscriptname)]
2207 self.setDirty(True) 2300 self.setDirty(True)
2208 QApplication.restoreOverrideCursor() 2301 QApplication.restoreOverrideCursor()
2209 2302
2210 def __showProperties(self): 2303 def __showProperties(self):
2211 """ 2304 """
2238 os.makedirs(tp) 2331 os.makedirs(tp)
2239 if tp != self.ppath and tp not in self.subdirs: 2332 if tp != self.ppath and tp not in self.subdirs:
2240 self.subdirs.append(tp) 2333 self.subdirs.append(tp)
2241 2334
2242 if self.pdata["TRANSLATIONSBINPATH"]: 2335 if self.pdata["TRANSLATIONSBINPATH"]:
2243 tp = os.path.join(self.ppath, self.pdata["TRANSLATIONSBINPATH"][0]) 2336 tp = os.path.join(
2337 self.ppath, self.pdata["TRANSLATIONSBINPATH"][0])
2244 if not os.path.isdir(tp): 2338 if not os.path.isdir(tp):
2245 os.makedirs(tp) 2339 os.makedirs(tp)
2246 if tp != self.ppath and tp not in self.subdirs: 2340 if tp != self.ppath and tp not in self.subdirs:
2247 self.subdirs.append(tp) 2341 self.subdirs.append(tp)
2248 2342
2249 self.pluginGrp.setEnabled(self.pdata["PROJECTTYPE"][0] == "E4Plugin") 2343 self.pluginGrp.setEnabled(
2344 self.pdata["PROJECTTYPE"][0] == "E4Plugin")
2250 2345
2251 self.__model.projectPropertiesChanged() 2346 self.__model.projectPropertiesChanged()
2252 self.projectPropertiesChanged.emit() 2347 self.projectPropertiesChanged.emit()
2253 2348
2254 def __showUserProperties(self): 2349 def __showUserProperties(self):
2255 """ 2350 """
2256 Private slot to display the user specific properties dialog. 2351 Private slot to display the user specific properties dialog.
2257 """ 2352 """
2258 vcsSystem = self.pdata["VCS"] and self.pdata["VCS"][0] or None 2353 vcsSystem = self.pdata["VCS"] and self.pdata["VCS"][0] or None
2259 vcsSystemOverride = \ 2354 vcsSystemOverride = self.pudata["VCSOVERRIDE"] and \
2260 self.pudata["VCSOVERRIDE"] and self.pudata["VCSOVERRIDE"][0] or None 2355 self.pudata["VCSOVERRIDE"][0] or None
2261 2356
2262 from .UserPropertiesDialog import UserPropertiesDialog 2357 from .UserPropertiesDialog import UserPropertiesDialog
2263 dlg = UserPropertiesDialog(self) 2358 dlg = UserPropertiesDialog(self)
2264 if dlg.exec_() == QDialog.Accepted: 2359 if dlg.exec_() == QDialog.Accepted:
2265 dlg.storeData() 2360 dlg.storeData()
2280 # reinit VCS 2375 # reinit VCS
2281 self.vcs = self.initVCS() 2376 self.vcs = self.initVCS()
2282 # start the VCS monitor thread 2377 # start the VCS monitor thread
2283 if self.vcs is not None: 2378 if self.vcs is not None:
2284 self.vcs.startStatusMonitor(self) 2379 self.vcs.startStatusMonitor(self)
2285 self.vcs.vcsStatusMonitorData.connect(self.__model.changeVCSStates) 2380 self.vcs.vcsStatusMonitorData.connect(
2286 self.vcs.vcsStatusMonitorStatus.connect(self.__statusMonitorStatus) 2381 self.__model.changeVCSStates)
2382 self.vcs.vcsStatusMonitorStatus.connect(
2383 self.__statusMonitorStatus)
2287 self.vcs.vcsStatusChanged.connect(self.__vcsStatusChanged) 2384 self.vcs.vcsStatusChanged.connect(self.__vcsStatusChanged)
2288 self.reinitVCS.emit() 2385 self.reinitVCS.emit()
2289 2386
2290 if self.pudata["VCSSTATUSMONITORINTERVAL"]: 2387 if self.pudata["VCSSTATUSMONITORINTERVAL"]:
2291 self.setStatusMonitorInterval( 2388 self.setStatusMonitorInterval(
2317 2414
2318 def getEditorLexerAssoc(self, filename): 2415 def getEditorLexerAssoc(self, filename):
2319 """ 2416 """
2320 Public method to retrieve a lexer association. 2417 Public method to retrieve a lexer association.
2321 2418
2322 @param filename filename used to determine the associated lexer language (string) 2419 @param filename filename used to determine the associated lexer
2420 language (string)
2323 @return the requested lexer language (string) 2421 @return the requested lexer language (string)
2324 """ 2422 """
2325 # try user settings first 2423 # try user settings first
2326 for pattern, language in list(self.pdata["LEXERASSOCS"].items()): 2424 for pattern, language in list(self.pdata["LEXERASSOCS"].items()):
2327 if fnmatch.fnmatch(filename, pattern): 2425 if fnmatch.fnmatch(filename, pattern):
2352 2450
2353 if fn is None: 2451 if fn is None:
2354 fn = E5FileDialog.getOpenFileName( 2452 fn = E5FileDialog.getOpenFileName(
2355 self.parent(), 2453 self.parent(),
2356 self.trUtf8("Open project"), 2454 self.trUtf8("Open project"),
2357 Preferences.getMultiProject("Workspace") or Utilities.getHomeDir(), 2455 Preferences.getMultiProject("Workspace") or \
2456 Utilities.getHomeDir(),
2358 self.trUtf8("Project Files (*.e4p)")) 2457 self.trUtf8("Project Files (*.e4p)"))
2359 2458
2360 QApplication.processEvents() 2459 QApplication.processEvents()
2361 2460
2362 if fn: 2461 if fn:
2388 self.vcs = self.initVCS() 2487 self.vcs = self.initVCS()
2389 if self.vcs is None and self.isDirty() == oldState: 2488 if self.vcs is None and self.isDirty() == oldState:
2390 # check, if project is version controlled 2489 # check, if project is version controlled
2391 pluginManager = e5App().getObject("PluginManager") 2490 pluginManager = e5App().getObject("PluginManager")
2392 for indicator, vcsData in \ 2491 for indicator, vcsData in \
2393 list(pluginManager.getVcsSystemIndicators().items()): 2492 pluginManager.getVcsSystemIndicators().items():
2394 if os.path.exists(os.path.join(self.ppath, indicator)): 2493 if os.path.exists(
2494 os.path.join(self.ppath, indicator)):
2395 if len(vcsData) > 1: 2495 if len(vcsData) > 1:
2396 vcsList = [] 2496 vcsList = []
2397 for vcsSystemStr, vcsSystemDisplay in vcsData: 2497 for vcsSystemStr, vcsSystemDisplay in \
2498 vcsData:
2398 vcsList.append(vcsSystemDisplay) 2499 vcsList.append(vcsSystemDisplay)
2399 QApplication.restoreOverrideCursor() 2500 QApplication.restoreOverrideCursor()
2400 res, vcs_ok = QInputDialog.getItem( 2501 res, vcs_ok = QInputDialog.getItem(
2401 None, 2502 None,
2402 self.trUtf8("New Project"), 2503 self.trUtf8("New Project"),
2403 self.trUtf8("Select Version Control System"), 2504 self.trUtf8(
2505 "Select Version Control System"),
2404 vcsList, 2506 vcsList,
2405 0, False) 2507 0, False)
2406 QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) 2508 QApplication.setOverrideCursor(
2509 QCursor(Qt.WaitCursor))
2407 QApplication.processEvents() 2510 QApplication.processEvents()
2408 if vcs_ok: 2511 if vcs_ok:
2409 for vcsSystemStr, vcsSystemDisplay in vcsData: 2512 for vcsSystemStr, vcsSystemDisplay in \
2513 vcsData:
2410 if res == vcsSystemDisplay: 2514 if res == vcsSystemDisplay:
2411 vcsSystem = vcsSystemStr 2515 vcsSystem = vcsSystemStr
2412 break 2516 break
2413 else: 2517 else:
2414 vcsSystem = "None" 2518 vcsSystem = "None"
2418 vcsSystem = vcsData[0][0] 2522 vcsSystem = vcsData[0][0]
2419 self.pdata["VCS"] = [vcsSystem] 2523 self.pdata["VCS"] = [vcsSystem]
2420 self.vcs = self.initVCS() 2524 self.vcs = self.initVCS()
2421 self.setDirty(True) 2525 self.setDirty(True)
2422 if self.vcs is not None and \ 2526 if self.vcs is not None and \
2423 self.vcs.vcsRegisteredState(self.ppath) != self.vcs.canBeCommitted: 2527 (self.vcs.vcsRegisteredState(self.ppath) !=
2528 self.vcs.canBeCommitted):
2424 self.pdata["VCS"] = ['None'] 2529 self.pdata["VCS"] = ['None']
2425 self.vcs = self.initVCS() 2530 self.vcs = self.initVCS()
2426 self.closeAct.setEnabled(True) 2531 self.closeAct.setEnabled(True)
2427 self.saveasAct.setEnabled(True) 2532 self.saveasAct.setEnabled(True)
2428 self.actGrp2.setEnabled(True) 2533 self.actGrp2.setEnabled(True)
2437 self.menuCheckAct.setEnabled(True) 2542 self.menuCheckAct.setEnabled(True)
2438 self.menuShowAct.setEnabled(True) 2543 self.menuShowAct.setEnabled(True)
2439 self.menuDiagramAct.setEnabled(True) 2544 self.menuDiagramAct.setEnabled(True)
2440 self.menuApidocAct.setEnabled(True) 2545 self.menuApidocAct.setEnabled(True)
2441 self.menuPackagersAct.setEnabled(True) 2546 self.menuPackagersAct.setEnabled(True)
2442 self.pluginGrp.setEnabled(self.pdata["PROJECTTYPE"][0] == "E4Plugin") 2547 self.pluginGrp.setEnabled(
2548 self.pdata["PROJECTTYPE"][0] == "E4Plugin")
2443 self.addLanguageAct.setEnabled( 2549 self.addLanguageAct.setEnabled(
2444 len(self.pdata["TRANSLATIONPATTERN"]) > 0 and \ 2550 len(self.pdata["TRANSLATIONPATTERN"]) > 0 and \
2445 self.pdata["TRANSLATIONPATTERN"][0] != '') 2551 self.pdata["TRANSLATIONPATTERN"][0] != '')
2446 2552
2447 self.__model.projectOpened() 2553 self.__model.projectOpened()
2459 2565
2460 if restoreSession: 2566 if restoreSession:
2461 # open the main script 2567 # open the main script
2462 if len(self.pdata["MAINSCRIPT"]) == 1: 2568 if len(self.pdata["MAINSCRIPT"]) == 1:
2463 self.sourceFile.emit( 2569 self.sourceFile.emit(
2464 os.path.join(self.ppath, self.pdata["MAINSCRIPT"][0])) 2570 os.path.join(
2571 self.ppath, self.pdata["MAINSCRIPT"][0]))
2465 2572
2466 # open a project session file being quiet about errors 2573 # open a project session file being quiet about errors
2467 if reopen: 2574 if reopen:
2468 self.__readSession(quiet=True, indicator="_tmp") 2575 self.__readSession(quiet=True, indicator="_tmp")
2469 elif Preferences.getProject("AutoLoadSession"): 2576 elif Preferences.getProject("AutoLoadSession"):
2470 self.__readSession(quiet=True) 2577 self.__readSession(quiet=True)
2471 2578
2472 # open a project debugger properties file being quiet about errors 2579 # open a project debugger properties file being quiet
2580 # about errors
2473 if Preferences.getProject("AutoLoadDbgProperties"): 2581 if Preferences.getProject("AutoLoadDbgProperties"):
2474 self.__readDebugProperties(True) 2582 self.__readDebugProperties(True)
2475 2583
2476 # start the VCS monitor thread 2584 # start the VCS monitor thread
2477 if self.vcs is not None: 2585 if self.vcs is not None:
2704 filesWithSyntaxErrors += 1 2812 filesWithSyntaxErrors += 1
2705 2813
2706 if reportSyntaxErrors and filesWithSyntaxErrors > 0: 2814 if reportSyntaxErrors and filesWithSyntaxErrors > 0:
2707 E5MessageBox.critical(self.ui, 2815 E5MessageBox.critical(self.ui,
2708 self.trUtf8("Syntax errors detected"), 2816 self.trUtf8("Syntax errors detected"),
2709 self.trUtf8("""The project contains %n file(s) with syntax errors.""", 2817 self.trUtf8(
2818 """The project contains %n file(s) with syntax errors.""",
2710 "", filesWithSyntaxErrors) 2819 "", filesWithSyntaxErrors)
2711 ) 2820 )
2712 return False 2821 return False
2713 else: 2822 else:
2714 return success 2823 return success
2734 filesWithSyntaxErrors += 1 2843 filesWithSyntaxErrors += 1
2735 2844
2736 if reportSyntaxErrors and filesWithSyntaxErrors > 0: 2845 if reportSyntaxErrors and filesWithSyntaxErrors > 0:
2737 E5MessageBox.critical(self.ui, 2846 E5MessageBox.critical(self.ui,
2738 self.trUtf8("Syntax errors detected"), 2847 self.trUtf8("Syntax errors detected"),
2739 self.trUtf8("""The project contains %n file(s) with syntax errors.""", 2848 self.trUtf8(
2849 """The project contains %n file(s) with syntax errors.""",
2740 "", filesWithSyntaxErrors) 2850 "", filesWithSyntaxErrors)
2741 ) 2851 )
2742 return False 2852 return False
2743 else: 2853 else:
2744 return success 2854 return success
2745 2855
2746 def getMainScript(self, normalized=False): 2856 def getMainScript(self, normalized=False):
2747 """ 2857 """
2748 Public method to return the main script filename. 2858 Public method to return the main script filename.
2749 2859
2750 @param normalized flag indicating a normalized filename is wanted (boolean) 2860 @param normalized flag indicating a normalized filename is wanted
2861 (boolean)
2751 @return filename of the projects main script (string) 2862 @return filename of the projects main script (string)
2752 """ 2863 """
2753 if len(self.pdata["MAINSCRIPT"]): 2864 if len(self.pdata["MAINSCRIPT"]):
2754 if normalized: 2865 if normalized:
2755 return os.path.join(self.ppath, self.pdata["MAINSCRIPT"][0]) 2866 return os.path.join(self.ppath, self.pdata["MAINSCRIPT"][0])
2760 2871
2761 def getSources(self, normalized=False): 2872 def getSources(self, normalized=False):
2762 """ 2873 """
2763 Public method to return the source script files. 2874 Public method to return the source script files.
2764 2875
2765 @param normalized flag indicating a normalized filename is wanted (boolean) 2876 @param normalized flag indicating a normalized filename is wanted
2877 (boolean)
2766 @return list of the projects scripts (list of string) 2878 @return list of the projects scripts (list of string)
2767 """ 2879 """
2768 if normalized: 2880 if normalized:
2769 return [os.path.join(self.ppath, fn) for fn in self.pdata["SOURCES"]] 2881 return [os.path.join(self.ppath, fn) for fn in
2882 self.pdata["SOURCES"]]
2770 else: 2883 else:
2771 return self.pdata["SOURCES"] 2884 return self.pdata["SOURCES"]
2772 2885
2773 def getProjectType(self): 2886 def getProjectType(self):
2774 """ 2887 """
2863 def startswithProjectPath(self, path): 2976 def startswithProjectPath(self, path):
2864 """ 2977 """
2865 Public method to check, if a path starts with the project path. 2978 Public method to check, if a path starts with the project path.
2866 2979
2867 @param path path to be checked (string) 2980 @param path path to be checked (string)
2981 @return flag indicating that the path starts with the project path
2982 (boolean)
2868 """ 2983 """
2869 if self.ppath: 2984 if self.ppath:
2870 if path == self.ppath: 2985 if path == self.ppath:
2871 return True 2986 return True
2872 elif Utilities.normcasepath(Utilities.toNativeSeparators(path)).startswith( 2987 elif Utilities.normcasepath(Utilities.toNativeSeparators(path))\
2873 Utilities.normcasepath(Utilities.toNativeSeparators(self.ppath + "/"))): 2988 .startswith(Utilities.normcasepath(
2989 Utilities.toNativeSeparators(self.ppath + "/"))):
2874 return True 2990 return True
2875 else: 2991 else:
2876 return False 2992 return False
2877 else: 2993 else:
2878 return False 2994 return False
2998 """ 3114 """
2999 return self.pdata["EOL"][0] == 0 3115 return self.pdata["EOL"][0] == 0
3000 3116
3001 def isProjectFile(self, fn): 3117 def isProjectFile(self, fn):
3002 """ 3118 """
3003 Public method used to check, if the passed in filename belongs to the project. 3119 Public method used to check, if the passed in filename belongs to the
3120 project.
3004 3121
3005 @param fn filename to be checked (string) 3122 @param fn filename to be checked (string)
3006 @return flag indicating membership (boolean) 3123 @return flag indicating membership (boolean)
3007 """ 3124 """
3008 for group in ["SOURCES", "FORMS", "INTERFACES", 3125 for group in ["SOURCES", "FORMS", "INTERFACES",
3012 3129
3013 return False 3130 return False
3014 3131
3015 def __checkProjectFileGroup(self, fn, group): 3132 def __checkProjectFileGroup(self, fn, group):
3016 """ 3133 """
3017 Private method to check, if a file is in a specific file group of the project. 3134 Private method to check, if a file is in a specific file group of the
3135 project.
3018 3136
3019 @param fn filename to be checked (string) 3137 @param fn filename to be checked (string)
3020 @param group group to check (string) 3138 @param group group to check (string)
3021 @return flag indicating membership (boolean) 3139 @return flag indicating membership (boolean)
3022 """ 3140 """
3042 3160
3043 return False 3161 return False
3044 3162
3045 def isProjectSource(self, fn): 3163 def isProjectSource(self, fn):
3046 """ 3164 """
3047 Public method used to check, if the passed in filename belongs to the project 3165 Public method used to check, if the passed in filename belongs to the
3048 sources. 3166 project sources.
3049 3167
3050 @param fn filename to be checked (string) 3168 @param fn filename to be checked (string)
3051 @return flag indicating membership (boolean) 3169 @return flag indicating membership (boolean)
3052 """ 3170 """
3053 return self.__checkProjectFileGroup(fn, "SOURCES") 3171 return self.__checkProjectFileGroup(fn, "SOURCES")
3054 3172
3055 def isProjectForm(self, fn): 3173 def isProjectForm(self, fn):
3056 """ 3174 """
3057 Public method used to check, if the passed in filename belongs to the project 3175 Public method used to check, if the passed in filename belongs to the
3058 forms. 3176 project forms.
3059 3177
3060 @param fn filename to be checked (string) 3178 @param fn filename to be checked (string)
3061 @return flag indicating membership (boolean) 3179 @return flag indicating membership (boolean)
3062 """ 3180 """
3063 return self.__checkProjectFileGroup(fn, "FORMS") 3181 return self.__checkProjectFileGroup(fn, "FORMS")
3064 3182
3065 def isProjectInterface(self, fn): 3183 def isProjectInterface(self, fn):
3066 """ 3184 """
3067 Public method used to check, if the passed in filename belongs to the project 3185 Public method used to check, if the passed in filename belongs to the
3068 interfaces. 3186 project interfaces.
3069 3187
3070 @param fn filename to be checked (string) 3188 @param fn filename to be checked (string)
3071 @return flag indicating membership (boolean) 3189 @return flag indicating membership (boolean)
3072 """ 3190 """
3073 return self.__checkProjectFileGroup(fn, "INTERFACES") 3191 return self.__checkProjectFileGroup(fn, "INTERFACES")
3074 3192
3075 def isProjectResource(self, fn): 3193 def isProjectResource(self, fn):
3076 """ 3194 """
3077 Public method used to check, if the passed in filename belongs to the project 3195 Public method used to check, if the passed in filename belongs to the
3078 resources. 3196 project resources.
3079 3197
3080 @param fn filename to be checked (string) 3198 @param fn filename to be checked (string)
3081 @return flag indicating membership (boolean) 3199 @return flag indicating membership (boolean)
3082 """ 3200 """
3083 return self.__checkProjectFileGroup(fn, "RESOURCES") 3201 return self.__checkProjectFileGroup(fn, "RESOURCES")
3138 self.actions.append(self.saveAct) 3256 self.actions.append(self.saveAct)
3139 3257
3140 self.saveasAct = E5Action(self.trUtf8('Save project as'), 3258 self.saveasAct = E5Action(self.trUtf8('Save project as'),
3141 UI.PixmapCache.getIcon("projectSaveAs.png"), 3259 UI.PixmapCache.getIcon("projectSaveAs.png"),
3142 self.trUtf8('Save &as...'), 0, 0, self, 'project_save_as') 3260 self.trUtf8('Save &as...'), 0, 0, self, 'project_save_as')
3143 self.saveasAct.setStatusTip(self.trUtf8('Save the current project to a new file')) 3261 self.saveasAct.setStatusTip(self.trUtf8(
3262 'Save the current project to a new file'))
3144 self.saveasAct.setWhatsThis(self.trUtf8( 3263 self.saveasAct.setWhatsThis(self.trUtf8(
3145 """<b>Save as</b>""" 3264 """<b>Save as</b>"""
3146 """<p>This saves the current project to a new file.</p>""" 3265 """<p>This saves the current project to a new file.</p>"""
3147 )) 3266 ))
3148 self.saveasAct.triggered[()].connect(self.saveProjectAs) 3267 self.saveasAct.triggered[()].connect(self.saveProjectAs)
3152 3271
3153 self.addFilesAct = E5Action(self.trUtf8('Add files to project'), 3272 self.addFilesAct = E5Action(self.trUtf8('Add files to project'),
3154 UI.PixmapCache.getIcon("fileMisc.png"), 3273 UI.PixmapCache.getIcon("fileMisc.png"),
3155 self.trUtf8('Add &files...'), 0, 0, 3274 self.trUtf8('Add &files...'), 0, 0,
3156 self.actGrp2, 'project_add_file') 3275 self.actGrp2, 'project_add_file')
3157 self.addFilesAct.setStatusTip(self.trUtf8('Add files to the current project')) 3276 self.addFilesAct.setStatusTip(self.trUtf8(
3277 'Add files to the current project'))
3158 self.addFilesAct.setWhatsThis(self.trUtf8( 3278 self.addFilesAct.setWhatsThis(self.trUtf8(
3159 """<b>Add files...</b>""" 3279 """<b>Add files...</b>"""
3160 """<p>This opens a dialog for adding files""" 3280 """<p>This opens a dialog for adding files"""
3161 """ to the current project. The place to add is""" 3281 """ to the current project. The place to add is"""
3162 """ determined by the file extension.</p>""" 3282 """ determined by the file extension.</p>"""
3163 )) 3283 ))
3164 self.addFilesAct.triggered[()].connect(self.addFiles) 3284 self.addFilesAct.triggered[()].connect(self.addFiles)
3165 self.actions.append(self.addFilesAct) 3285 self.actions.append(self.addFilesAct)
3166 3286
3167 self.addDirectoryAct = E5Action(self.trUtf8('Add directory to project'), 3287 self.addDirectoryAct = E5Action(
3168 UI.PixmapCache.getIcon("dirOpen.png"), 3288 self.trUtf8('Add directory to project'),
3169 self.trUtf8('Add directory...'), 0, 0, 3289 UI.PixmapCache.getIcon("dirOpen.png"),
3170 self.actGrp2, 'project_add_directory') 3290 self.trUtf8('Add directory...'), 0, 0,
3291 self.actGrp2, 'project_add_directory')
3171 self.addDirectoryAct.setStatusTip( 3292 self.addDirectoryAct.setStatusTip(
3172 self.trUtf8('Add a directory to the current project')) 3293 self.trUtf8('Add a directory to the current project'))
3173 self.addDirectoryAct.setWhatsThis(self.trUtf8( 3294 self.addDirectoryAct.setWhatsThis(self.trUtf8(
3174 """<b>Add directory...</b>""" 3295 """<b>Add directory...</b>"""
3175 """<p>This opens a dialog for adding a directory""" 3296 """<p>This opens a dialog for adding a directory"""
3176 """ to the current project.</p>""" 3297 """ to the current project.</p>"""
3177 )) 3298 ))
3178 self.addDirectoryAct.triggered[()].connect(self.addDirectory) 3299 self.addDirectoryAct.triggered[()].connect(self.addDirectory)
3179 self.actions.append(self.addDirectoryAct) 3300 self.actions.append(self.addDirectoryAct)
3180 3301
3181 self.addLanguageAct = E5Action(self.trUtf8('Add translation to project'), 3302 self.addLanguageAct = E5Action(
3182 UI.PixmapCache.getIcon("linguist4.png"), 3303 self.trUtf8('Add translation to project'),
3183 self.trUtf8('Add &translation...'), 0, 0, 3304 UI.PixmapCache.getIcon("linguist4.png"),
3184 self.actGrp2, 'project_add_translation') 3305 self.trUtf8('Add &translation...'), 0, 0,
3306 self.actGrp2, 'project_add_translation')
3185 self.addLanguageAct.setStatusTip( 3307 self.addLanguageAct.setStatusTip(
3186 self.trUtf8('Add a translation to the current project')) 3308 self.trUtf8('Add a translation to the current project'))
3187 self.addLanguageAct.setWhatsThis(self.trUtf8( 3309 self.addLanguageAct.setWhatsThis(self.trUtf8(
3188 """<b>Add translation...</b>""" 3310 """<b>Add translation...</b>"""
3189 """<p>This opens a dialog for add a translation""" 3311 """<p>This opens a dialog for add a translation"""
3193 self.actions.append(self.addLanguageAct) 3315 self.actions.append(self.addLanguageAct)
3194 3316
3195 act = E5Action(self.trUtf8('Search new files'), 3317 act = E5Action(self.trUtf8('Search new files'),
3196 self.trUtf8('Searc&h new files...'), 0, 0, 3318 self.trUtf8('Searc&h new files...'), 0, 0,
3197 self.actGrp2, 'project_search_new_files') 3319 self.actGrp2, 'project_search_new_files')
3198 act.setStatusTip(self.trUtf8('Search new files in the project directory.')) 3320 act.setStatusTip(self.trUtf8(
3321 'Search new files in the project directory.'))
3199 act.setWhatsThis(self.trUtf8( 3322 act.setWhatsThis(self.trUtf8(
3200 """<b>Search new files...</b>""" 3323 """<b>Search new files...</b>"""
3201 """<p>This searches for new files (sources, *.ui, *.idl) in the project""" 3324 """<p>This searches for new files (sources, *.ui, *.idl) in"""
3202 """ directory and registered subdirectories.</p>""" 3325 """ the project directory and registered subdirectories.</p>"""
3203 )) 3326 ))
3204 act.triggered[()].connect(self.__searchNewFiles) 3327 act.triggered[()].connect(self.__searchNewFiles)
3205 self.actions.append(act) 3328 self.actions.append(act)
3206 3329
3207 self.propsAct = E5Action(self.trUtf8('Project properties'), 3330 self.propsAct = E5Action(self.trUtf8('Project properties'),
3208 UI.PixmapCache.getIcon("projectProps.png"), 3331 UI.PixmapCache.getIcon("projectProps.png"),
3209 self.trUtf8('&Properties...'), 0, 0, self, 'project_properties') 3332 self.trUtf8('&Properties...'), 0, 0, self,
3333 'project_properties')
3210 self.propsAct.setStatusTip(self.trUtf8('Show the project properties')) 3334 self.propsAct.setStatusTip(self.trUtf8('Show the project properties'))
3211 self.propsAct.setWhatsThis(self.trUtf8( 3335 self.propsAct.setWhatsThis(self.trUtf8(
3212 """<b>Properties...</b>""" 3336 """<b>Properties...</b>"""
3213 """<p>This shows a dialog to edit the project properties.</p>""" 3337 """<p>This shows a dialog to edit the project properties.</p>"""
3214 )) 3338 ))
3215 self.propsAct.triggered[()].connect(self.__showProperties) 3339 self.propsAct.triggered[()].connect(self.__showProperties)
3216 self.actions.append(self.propsAct) 3340 self.actions.append(self.propsAct)
3217 3341
3218 self.userPropsAct = E5Action(self.trUtf8('User project properties'), 3342 self.userPropsAct = E5Action(self.trUtf8('User project properties'),
3219 UI.PixmapCache.getIcon("projectUserProps.png"), 3343 UI.PixmapCache.getIcon("projectUserProps.png"),
3220 self.trUtf8('&User Properties...'), 0, 0, self, 'project_user_properties') 3344 self.trUtf8('&User Properties...'), 0, 0, self,
3345 'project_user_properties')
3221 self.userPropsAct.setStatusTip(self.trUtf8( 3346 self.userPropsAct.setStatusTip(self.trUtf8(
3222 'Show the user specific project properties')) 3347 'Show the user specific project properties'))
3223 self.userPropsAct.setWhatsThis(self.trUtf8( 3348 self.userPropsAct.setWhatsThis(self.trUtf8(
3224 """<b>User Properties...</b>""" 3349 """<b>User Properties...</b>"""
3225 """<p>This shows a dialog to edit the user specific project properties.</p>""" 3350 """<p>This shows a dialog to edit the user specific project"""
3351 """ properties.</p>"""
3226 )) 3352 ))
3227 self.userPropsAct.triggered[()].connect(self.__showUserProperties) 3353 self.userPropsAct.triggered[()].connect(self.__showUserProperties)
3228 self.actions.append(self.userPropsAct) 3354 self.actions.append(self.userPropsAct)
3229 3355
3230 self.filetypesAct = E5Action(self.trUtf8('Filetype Associations'), 3356 self.filetypesAct = E5Action(self.trUtf8('Filetype Associations'),
3232 self, 'project_filetype_associatios') 3358 self, 'project_filetype_associatios')
3233 self.filetypesAct.setStatusTip( 3359 self.filetypesAct.setStatusTip(
3234 self.trUtf8('Show the project filetype associations')) 3360 self.trUtf8('Show the project filetype associations'))
3235 self.filetypesAct.setWhatsThis(self.trUtf8( 3361 self.filetypesAct.setWhatsThis(self.trUtf8(
3236 """<b>Filetype Associations...</b>""" 3362 """<b>Filetype Associations...</b>"""
3237 """<p>This shows a dialog to edit the filetype associations of the project.""" 3363 """<p>This shows a dialog to edit the filetype associations of"""
3238 """ These associations determine the type (source, form, interface""" 3364 """ the project. These associations determine the type"""
3239 """ or others) with a filename pattern. They are used when adding a file""" 3365 """ (source, form, interface or others) with a filename"""
3240 """ to the project and when performing a search for new files.</p>""" 3366 """ pattern. They are used when adding a file to the project"""
3367 """ and when performing a search for new files.</p>"""
3241 )) 3368 ))
3242 self.filetypesAct.triggered[()].connect(self.__showFiletypeAssociations) 3369 self.filetypesAct.triggered[()].connect(
3370 self.__showFiletypeAssociations)
3243 self.actions.append(self.filetypesAct) 3371 self.actions.append(self.filetypesAct)
3244 3372
3245 self.lexersAct = E5Action(self.trUtf8('Lexer Associations'), 3373 self.lexersAct = E5Action(self.trUtf8('Lexer Associations'),
3246 self.trUtf8('Lexer Associations...'), 0, 0, 3374 self.trUtf8('Lexer Associations...'), 0, 0,
3247 self, 'project_lexer_associatios') 3375 self, 'project_lexer_associatios')
3248 self.lexersAct.setStatusTip( 3376 self.lexersAct.setStatusTip(self.trUtf8(
3249 self.trUtf8('Show the project lexer associations (overriding defaults)')) 3377 'Show the project lexer associations (overriding defaults)'))
3250 self.lexersAct.setWhatsThis(self.trUtf8( 3378 self.lexersAct.setWhatsThis(self.trUtf8(
3251 """<b>Lexer Associations...</b>""" 3379 """<b>Lexer Associations...</b>"""
3252 """<p>This shows a dialog to edit the lexer associations of the project.""" 3380 """<p>This shows a dialog to edit the lexer associations of"""
3253 """ These associations override the global lexer associations. Lexers""" 3381 """ the project. These associations override the global lexer"""
3254 """ are used to highlight the editor text.</p>""" 3382 """ associations. Lexers are used to highlight the editor"""
3383 """ text.</p>"""
3255 )) 3384 ))
3256 self.lexersAct.triggered[()].connect(self.__showLexerAssociations) 3385 self.lexersAct.triggered[()].connect(self.__showLexerAssociations)
3257 self.actions.append(self.lexersAct) 3386 self.actions.append(self.lexersAct)
3258 3387
3259 self.dbgActGrp = createActionGroup(self) 3388 self.dbgActGrp = createActionGroup(self)
3262 self.trUtf8('Debugger &Properties...'), 0, 0, 3391 self.trUtf8('Debugger &Properties...'), 0, 0,
3263 self.dbgActGrp, 'project_debugger_properties') 3392 self.dbgActGrp, 'project_debugger_properties')
3264 act.setStatusTip(self.trUtf8('Show the debugger properties')) 3393 act.setStatusTip(self.trUtf8('Show the debugger properties'))
3265 act.setWhatsThis(self.trUtf8( 3394 act.setWhatsThis(self.trUtf8(
3266 """<b>Debugger Properties...</b>""" 3395 """<b>Debugger Properties...</b>"""
3267 """<p>This shows a dialog to edit project specific debugger settings.</p>""" 3396 """<p>This shows a dialog to edit project specific debugger"""
3397 """ settings.</p>"""
3268 )) 3398 ))
3269 act.triggered[()].connect(self.__showDebugProperties) 3399 act.triggered[()].connect(self.__showDebugProperties)
3270 self.actions.append(act) 3400 self.actions.append(act)
3271 3401
3272 act = E5Action(self.trUtf8('Load'), 3402 act = E5Action(self.trUtf8('Load'),
3368 self.chkGrp, 'project_code_metrics') 3498 self.chkGrp, 'project_code_metrics')
3369 self.codeMetricsAct.setStatusTip( 3499 self.codeMetricsAct.setStatusTip(
3370 self.trUtf8('Show some code metrics for the project.')) 3500 self.trUtf8('Show some code metrics for the project.'))
3371 self.codeMetricsAct.setWhatsThis(self.trUtf8( 3501 self.codeMetricsAct.setWhatsThis(self.trUtf8(
3372 """<b>Code Metrics...</b>""" 3502 """<b>Code Metrics...</b>"""
3373 """<p>This shows some code metrics for all Python files in the project.</p>""" 3503 """<p>This shows some code metrics for all Python files in"""
3504 """ the project.</p>"""
3374 )) 3505 ))
3375 self.codeMetricsAct.triggered[()].connect(self.__showCodeMetrics) 3506 self.codeMetricsAct.triggered[()].connect(self.__showCodeMetrics)
3376 self.actions.append(self.codeMetricsAct) 3507 self.actions.append(self.codeMetricsAct)
3377 3508
3378 self.codeCoverageAct = E5Action(self.trUtf8('Python Code Coverage'), 3509 self.codeCoverageAct = E5Action(self.trUtf8('Python Code Coverage'),
3380 self.chkGrp, 'project_code_coverage') 3511 self.chkGrp, 'project_code_coverage')
3381 self.codeCoverageAct.setStatusTip( 3512 self.codeCoverageAct.setStatusTip(
3382 self.trUtf8('Show code coverage information for the project.')) 3513 self.trUtf8('Show code coverage information for the project.'))
3383 self.codeCoverageAct.setWhatsThis(self.trUtf8( 3514 self.codeCoverageAct.setWhatsThis(self.trUtf8(
3384 """<b>Code Coverage...</b>""" 3515 """<b>Code Coverage...</b>"""
3385 """<p>This shows the code coverage information for all Python files""" 3516 """<p>This shows the code coverage information for all Python"""
3386 """ in the project.</p>""" 3517 """ files in the project.</p>"""
3387 )) 3518 ))
3388 self.codeCoverageAct.triggered[()].connect(self.__showCodeCoverage) 3519 self.codeCoverageAct.triggered[()].connect(self.__showCodeCoverage)
3389 self.actions.append(self.codeCoverageAct) 3520 self.actions.append(self.codeCoverageAct)
3390 3521
3391 self.codeProfileAct = E5Action(self.trUtf8('Profile Data'), 3522 self.codeProfileAct = E5Action(self.trUtf8('Profile Data'),
3400 self.codeProfileAct.triggered[()].connect(self.__showProfileData) 3531 self.codeProfileAct.triggered[()].connect(self.__showProfileData)
3401 self.actions.append(self.codeProfileAct) 3532 self.actions.append(self.codeProfileAct)
3402 3533
3403 self.graphicsGrp = createActionGroup(self) 3534 self.graphicsGrp = createActionGroup(self)
3404 3535
3405 self.applicationDiagramAct = E5Action(self.trUtf8('Application Diagram'), 3536 self.applicationDiagramAct = E5Action(
3406 self.trUtf8('&Application Diagram...'), 0, 0, 3537 self.trUtf8('Application Diagram'),
3407 self.graphicsGrp, 'project_application_diagram') 3538 self.trUtf8('&Application Diagram...'), 0, 0,
3539 self.graphicsGrp, 'project_application_diagram')
3408 self.applicationDiagramAct.setStatusTip( 3540 self.applicationDiagramAct.setStatusTip(
3409 self.trUtf8('Show a diagram of the project.')) 3541 self.trUtf8('Show a diagram of the project.'))
3410 self.applicationDiagramAct.setWhatsThis(self.trUtf8( 3542 self.applicationDiagramAct.setWhatsThis(self.trUtf8(
3411 """<b>Application Diagram...</b>""" 3543 """<b>Application Diagram...</b>"""
3412 """<p>This shows a diagram of the project.</p>""" 3544 """<p>This shows a diagram of the project.</p>"""
3413 )) 3545 ))
3414 self.applicationDiagramAct.triggered[()].connect(self.handleApplicationDiagram) 3546 self.applicationDiagramAct.triggered[()].connect(
3547 self.handleApplicationDiagram)
3415 self.actions.append(self.applicationDiagramAct) 3548 self.actions.append(self.applicationDiagramAct)
3416 3549
3417 self.loadDiagramAct = E5Action(self.trUtf8('Load Diagram'), 3550 self.loadDiagramAct = E5Action(self.trUtf8('Load Diagram'),
3418 self.trUtf8('&Load Diagram...'), 0, 0, 3551 self.trUtf8('&Load Diagram...'), 0, 0,
3419 self.graphicsGrp, 'project_load_diagram') 3552 self.graphicsGrp, 'project_load_diagram')
3434 self.pluginGrp, 'project_plugin_pkglist') 3567 self.pluginGrp, 'project_plugin_pkglist')
3435 self.pluginPkgListAct.setStatusTip( 3568 self.pluginPkgListAct.setStatusTip(
3436 self.trUtf8('Create an initial PKGLIST file for an eric5 plugin.')) 3569 self.trUtf8('Create an initial PKGLIST file for an eric5 plugin.'))
3437 self.pluginPkgListAct.setWhatsThis(self.trUtf8( 3570 self.pluginPkgListAct.setWhatsThis(self.trUtf8(
3438 """<b>Create Package List</b>""" 3571 """<b>Create Package List</b>"""
3439 """<p>This creates an initial list of files to include in an eric5 """ 3572 """<p>This creates an initial list of files to include in an"""
3440 """plugin archive. The list is created from the project file.</p>""" 3573 """ eric5 plugin archive. The list is created from the project"""
3574 """ file.</p>"""
3441 )) 3575 ))
3442 self.pluginPkgListAct.triggered[()].connect(self.__pluginCreatePkgList) 3576 self.pluginPkgListAct.triggered[()].connect(self.__pluginCreatePkgList)
3443 self.actions.append(self.pluginPkgListAct) 3577 self.actions.append(self.pluginPkgListAct)
3444 3578
3445 self.pluginArchiveAct = E5Action(self.trUtf8('Create Plugin Archive'), 3579 self.pluginArchiveAct = E5Action(self.trUtf8('Create Plugin Archive'),
3448 self.pluginGrp, 'project_plugin_archive') 3582 self.pluginGrp, 'project_plugin_archive')
3449 self.pluginArchiveAct.setStatusTip( 3583 self.pluginArchiveAct.setStatusTip(
3450 self.trUtf8('Create an eric5 plugin archive file.')) 3584 self.trUtf8('Create an eric5 plugin archive file.'))
3451 self.pluginArchiveAct.setWhatsThis(self.trUtf8( 3585 self.pluginArchiveAct.setWhatsThis(self.trUtf8(
3452 """<b>Create Plugin Archive</b>""" 3586 """<b>Create Plugin Archive</b>"""
3453 """<p>This creates an eric5 plugin archive file using the list of files """ 3587 """<p>This creates an eric5 plugin archive file using the list"""
3454 """given in the PKGLIST file. The archive name is built from the main """ 3588 """ of files given in the PKGLIST file. The archive name is"""
3455 """script name.</p>""" 3589 """ built from the main script name.</p>"""
3456 )) 3590 ))
3457 self.pluginArchiveAct.triggered[()].connect(self.__pluginCreateArchive) 3591 self.pluginArchiveAct.triggered[()].connect(self.__pluginCreateArchive)
3458 self.actions.append(self.pluginArchiveAct) 3592 self.actions.append(self.pluginArchiveAct)
3459 3593
3460 self.pluginSArchiveAct = E5Action(self.trUtf8('Create Plugin Archive (Snapshot)'), 3594 self.pluginSArchiveAct = E5Action(
3461 UI.PixmapCache.getIcon("pluginArchiveSnapshot.png"), 3595 self.trUtf8('Create Plugin Archive (Snapshot)'),
3462 self.trUtf8('Create Plugin Archive (&Snapshot)'), 0, 0, 3596 UI.PixmapCache.getIcon("pluginArchiveSnapshot.png"),
3463 self.pluginGrp, 'project_plugin_sarchive') 3597 self.trUtf8('Create Plugin Archive (&Snapshot)'), 0, 0,
3464 self.pluginSArchiveAct.setStatusTip( 3598 self.pluginGrp, 'project_plugin_sarchive')
3465 self.trUtf8('Create an eric5 plugin archive file (snapshot release).')) 3599 self.pluginSArchiveAct.setStatusTip(self.trUtf8(
3600 'Create an eric5 plugin archive file (snapshot release).'))
3466 self.pluginSArchiveAct.setWhatsThis(self.trUtf8( 3601 self.pluginSArchiveAct.setWhatsThis(self.trUtf8(
3467 """<b>Create Plugin Archive (Snapshot)</b>""" 3602 """<b>Create Plugin Archive (Snapshot)</b>"""
3468 """<p>This creates an eric5 plugin archive file using the list of files """ 3603 """<p>This creates an eric5 plugin archive file using the list"""
3469 """given in the PKGLIST file. The archive name is built from the main """ 3604 """ of files given in the PKGLIST file. The archive name is"""
3470 """script name. The version entry of the main script is modified to """ 3605 """ built from the main script name. The version entry of the"""
3471 """reflect a snapshot release.</p>""" 3606 """ main script is modified to reflect a snapshot release.</p>"""
3472 )) 3607 ))
3473 self.pluginSArchiveAct.triggered[()].connect(self.__pluginCreateSnapshotArchive) 3608 self.pluginSArchiveAct.triggered[()].connect(
3609 self.__pluginCreateSnapshotArchive)
3474 self.actions.append(self.pluginSArchiveAct) 3610 self.actions.append(self.pluginSArchiveAct)
3475 3611
3476 self.closeAct.setEnabled(False) 3612 self.closeAct.setEnabled(False)
3477 self.saveAct.setEnabled(False) 3613 self.saveAct.setEnabled(False)
3478 self.saveasAct.setEnabled(False) 3614 self.saveasAct.setEnabled(False)
3603 3739
3604 def initToolbar(self, toolbarManager): 3740 def initToolbar(self, toolbarManager):
3605 """ 3741 """
3606 Public slot to initialize the project toolbar. 3742 Public slot to initialize the project toolbar.
3607 3743
3608 @param toolbarManager reference to a toolbar manager object (E5ToolBarManager) 3744 @param toolbarManager reference to a toolbar manager object
3745 (E5ToolBarManager)
3609 @return the toolbar generated (QToolBar) 3746 @return the toolbar generated (QToolBar)
3610 """ 3747 """
3611 tb = QToolBar(self.trUtf8("Project"), self.ui) 3748 tb = QToolBar(self.trUtf8("Project"), self.ui)
3612 tb.setIconSize(UI.Config.ToolBarIconSize) 3749 tb.setIconSize(UI.Config.ToolBarIconSize)
3613 tb.setObjectName("ProjectToolbar") 3750 tb.setObjectName("ProjectToolbar")
3674 self.recentMenu.addSeparator() 3811 self.recentMenu.addSeparator()
3675 self.recentMenu.addAction(self.trUtf8('&Clear'), self.__clearRecent) 3812 self.recentMenu.addAction(self.trUtf8('&Clear'), self.__clearRecent)
3676 3813
3677 def __openRecent(self, act): 3814 def __openRecent(self, act):
3678 """ 3815 """
3679 Private method to open a project from the list of rencently opened projects. 3816 Private method to open a project from the list of rencently opened
3817 projects.
3680 3818
3681 @param act reference to the action that triggered (QAction) 3819 @param act reference to the action that triggered (QAction)
3682 """ 3820 """
3683 file = act.data() 3821 file = act.data()
3684 if file: 3822 if file:
3720 try: 3858 try:
3721 newSources = os.listdir(curpath) 3859 newSources = os.listdir(curpath)
3722 except OSError: 3860 except OSError:
3723 newSources = [] 3861 newSources = []
3724 if self.pdata["TRANSLATIONPATTERN"]: 3862 if self.pdata["TRANSLATIONPATTERN"]:
3725 pattern = self.pdata["TRANSLATIONPATTERN"][0].replace("%language%", "*") 3863 pattern = self.pdata["TRANSLATIONPATTERN"][0]\
3864 .replace("%language%", "*")
3726 else: 3865 else:
3727 pattern = "*.ts" 3866 pattern = "*.ts"
3728 binpattern = self.__binaryTranslationFile(pattern) 3867 binpattern = self.__binaryTranslationFile(pattern)
3729 for ns in newSources: 3868 for ns in newSources:
3730 # ignore hidden files and directories 3869 # ignore hidden files and directories
3735 ns.startswith('_'): 3874 ns.startswith('_'):
3736 # dot net hack 3875 # dot net hack
3737 continue 3876 continue
3738 3877
3739 # set fn to project relative name 3878 # set fn to project relative name
3740 # then reset ns to fully qualified name for insertion, possibly. 3879 # then reset ns to fully qualified name for insertion,
3880 # possibly.
3741 if dir == "": 3881 if dir == "":
3742 fn = ns 3882 fn = ns
3743 else: 3883 else:
3744 fn = os.path.join(dir, ns) 3884 fn = os.path.join(dir, ns)
3745 ns = os.path.abspath(os.path.join(curpath, ns)) 3885 ns = os.path.abspath(os.path.join(curpath, ns))
3752 dirs.append(d) 3892 dirs.append(d)
3753 continue 3893 continue
3754 3894
3755 filetype = "" 3895 filetype = ""
3756 bfn = os.path.basename(fn) 3896 bfn = os.path.basename(fn)
3757 for pattern in reversed(sorted(self.pdata["FILETYPES"].keys())): 3897 for pattern in reversed(
3898 sorted(self.pdata["FILETYPES"].keys())):
3758 if fnmatch.fnmatch(bfn, pattern): 3899 if fnmatch.fnmatch(bfn, pattern):
3759 filetype = self.pdata["FILETYPES"][pattern] 3900 filetype = self.pdata["FILETYPES"][pattern]
3760 break 3901 break
3761 3902
3762 if (filetype == "SOURCES" and fn not in self.pdata["SOURCES"]) or \ 3903 if (filetype == "SOURCES" and
3763 (filetype == "FORMS" and fn not in self.pdata["FORMS"]) or \ 3904 fn not in self.pdata["SOURCES"]) or \
3764 (filetype == "INTERFACES" and fn not in self.pdata["INTERFACES"]) or \ 3905 (filetype == "FORMS" and
3765 (filetype == "RESOURCES" and fn not in self.pdata["RESOURCES"]) or \ 3906 fn not in self.pdata["FORMS"]) or \
3907 (filetype == "INTERFACES" and
3908 fn not in self.pdata["INTERFACES"]) or \
3909 (filetype == "RESOURCES" and
3910 fn not in self.pdata["RESOURCES"]) or \
3766 (filetype == "OTHERS" and fn not in self.pdata["OTHERS"]): 3911 (filetype == "OTHERS" and fn not in self.pdata["OTHERS"]):
3767 if autoInclude and AI: 3912 if autoInclude and AI:
3768 self.appendFile(ns) 3913 self.appendFile(ns)
3769 else: 3914 else:
3770 newFiles.append(ns) 3915 newFiles.append(ns)
3771 elif filetype == "TRANSLATIONS" and fn not in self.pdata["TRANSLATIONS"]: 3916 elif filetype == "TRANSLATIONS" and \
3772 if fnmatch.fnmatch(ns, pattern) or fnmatch.fnmatch(ns, binpattern): 3917 fn not in self.pdata["TRANSLATIONS"]:
3918 if fnmatch.fnmatch(ns, pattern) or \
3919 fnmatch.fnmatch(ns, binpattern):
3773 if autoInclude and AI: 3920 if autoInclude and AI:
3774 self.appendFile(ns) 3921 self.appendFile(ns)
3775 else: 3922 else:
3776 newFiles.append(ns) 3923 newFiles.append(ns)
3777 3924
3803 for file in files: 3950 for file in files:
3804 self.appendFile(file) 3951 self.appendFile(file)
3805 3952
3806 def othersAdded(self, fn, updateModel=True): 3953 def othersAdded(self, fn, updateModel=True):
3807 """ 3954 """
3808 Public slot to be called, if something was added to the OTHERS project data area. 3955 Public slot to be called, if something was added to the OTHERS project
3956 data area.
3809 3957
3810 @param fn filename or directory name added (string) 3958 @param fn filename or directory name added (string)
3811 @param updateModel flag indicating an update of the model is requested (boolean) 3959 @param updateModel flag indicating an update of the model is requested
3960 (boolean)
3812 """ 3961 """
3813 self.projectOthersAdded.emit(fn) 3962 self.projectOthersAdded.emit(fn)
3814 updateModel and self.__model.addNewItem("OTHERS", fn) 3963 updateModel and self.__model.addNewItem("OTHERS", fn)
3815 3964
3816 def getActions(self): 3965 def getActions(self):
3874 def initVCS(self, vcsSystem=None, nooverride=False): 4023 def initVCS(self, vcsSystem=None, nooverride=False):
3875 """ 4024 """
3876 Public method used to instantiate a vcs system. 4025 Public method used to instantiate a vcs system.
3877 4026
3878 @param vcsSystem type of VCS to be used (string) 4027 @param vcsSystem type of VCS to be used (string)
3879 @param nooverride flag indicating to ignore an override request (boolean) 4028 @param nooverride flag indicating to ignore an override request
4029 (boolean)
3880 @return a reference to the vcs object 4030 @return a reference to the vcs object
3881 """ 4031 """
3882 vcs = None 4032 vcs = None
3883 forProject = True 4033 forProject = True
3884 override = False 4034 override = False
3913 if override: 4063 if override:
3914 # override failed, revert to original 4064 # override failed, revert to original
3915 QApplication.restoreOverrideCursor() 4065 QApplication.restoreOverrideCursor()
3916 E5MessageBox.critical(self.ui, 4066 E5MessageBox.critical(self.ui,
3917 self.trUtf8("Version Control System"), 4067 self.trUtf8("Version Control System"),
3918 self.trUtf8("<p>The selected VCS <b>{0}</b> could not be found." 4068 self.trUtf8(
3919 "<br/>Reverting override.</p><p>{1}</p>")\ 4069 "<p>The selected VCS <b>{0}</b> could not be"
4070 " found. <br/>Reverting override.</p><p>{1}</p>")
3920 .format(vcsSystem, msg)) 4071 .format(vcsSystem, msg))
3921 self.pudata["VCSOVERRIDE"] = [] 4072 self.pudata["VCSOVERRIDE"] = []
3922 return self.initVCS(nooverride=True) 4073 return self.initVCS(nooverride=True)
3923 4074
3924 QApplication.restoreOverrideCursor() 4075 QApplication.restoreOverrideCursor()
3925 E5MessageBox.critical(self.ui, 4076 E5MessageBox.critical(self.ui,
3926 self.trUtf8("Version Control System"), 4077 self.trUtf8("Version Control System"),
3927 self.trUtf8("<p>The selected VCS <b>{0}</b> could not be found.<br/>" 4078 self.trUtf8(
3928 "Disabling version control.</p><p>{1}</p>")\ 4079 "<p>The selected VCS <b>{0}</b> could not be"
3929 .format(vcsSystem, msg)) 4080 " found.<br/>Disabling version control.</p>"
4081 "<p>{1}</p>").format(vcsSystem, msg))
3930 vcs = None 4082 vcs = None
3931 if forProject: 4083 if forProject:
3932 self.pdata["VCS"][0] = 'None' 4084 self.pdata["VCS"][0] = 'None'
3933 self.setDirty(True) 4085 self.setDirty(True)
3934 else: 4086 else:
4030 self.codemetrics.show() 4182 self.codemetrics.show()
4031 self.codemetrics.prepare(files, self) 4183 self.codemetrics.prepare(files, self)
4032 4184
4033 def __showCodeCoverage(self): 4185 def __showCodeCoverage(self):
4034 """ 4186 """
4035 Private slot used to show the code coverage information for the project files. 4187 Private slot used to show the code coverage information for the
4188 project files.
4036 """ 4189 """
4037 fn = self.getMainScript(True) 4190 fn = self.getMainScript(True)
4038 if fn is None: 4191 if fn is None:
4039 E5MessageBox.critical(self.ui, 4192 E5MessageBox.critical(self.ui,
4040 self.trUtf8("Coverage Data"), 4193 self.trUtf8("Coverage Data"),
4172 """ 4325 """
4173 Private slot to load a diagram from file. 4326 Private slot to load a diagram from file.
4174 """ 4327 """
4175 from Graphics.UMLDialog import UMLDialog 4328 from Graphics.UMLDialog import UMLDialog
4176 self.loadedDiagram = None 4329 self.loadedDiagram = None
4177 loadedDiagram = UMLDialog(UMLDialog.NoDiagram, self, parent=self.parent()) 4330 loadedDiagram = UMLDialog(UMLDialog.NoDiagram,
4331 self, parent=self.parent())
4178 if loadedDiagram.load(): 4332 if loadedDiagram.load():
4179 self.loadedDiagram = loadedDiagram 4333 self.loadedDiagram = loadedDiagram
4180 self.loadedDiagram.show(fromFile=True) 4334 self.loadedDiagram.show(fromFile=True)
4181 4335
4182 ######################################################################### 4336 #########################################################################
4282 if not res: 4436 if not res:
4283 return # don't overwrite 4437 return # don't overwrite
4284 4438
4285 # build the list of entries 4439 # build the list of entries
4286 lst_ = [] 4440 lst_ = []
4287 for key in \ 4441 for key in ["SOURCES", "FORMS", "RESOURCES", "TRANSLATIONS",
4288 ["SOURCES", "FORMS", "RESOURCES", "TRANSLATIONS", "INTERFACES", "OTHERS"]: 4442 "INTERFACES", "OTHERS"]:
4289 lst_.extend(self.pdata[key]) 4443 lst_.extend(self.pdata[key])
4290 lst = [] 4444 lst = []
4291 for entry in lst_: 4445 for entry in lst_:
4292 if os.path.isdir(self.getAbsolutePath(entry)): 4446 if os.path.isdir(self.getAbsolutePath(entry)):
4293 lst.extend([self.getRelativePath(p) for p in 4447 lst.extend([self.getRelativePath(p) for p in
4304 if self.pdata["EOL"][0] == 0: 4458 if self.pdata["EOL"][0] == 0:
4305 newline = None 4459 newline = None
4306 else: 4460 else:
4307 newline = self.getEolString() 4461 newline = self.getEolString()
4308 pkglistFile = open(pkglist, "w", encoding="utf-8", newline=newline) 4462 pkglistFile = open(pkglist, "w", encoding="utf-8", newline=newline)
4309 pkglistFile.write("\n".join([Utilities.fromNativeSeparators(f) for f in lst])) 4463 pkglistFile.write(
4464 "\n".join([Utilities.fromNativeSeparators(f) for f in lst]))
4310 pkglistFile.write("\n") # ensure the file ends with an empty line 4465 pkglistFile.write("\n") # ensure the file ends with an empty line
4311 pkglistFile.close() 4466 pkglistFile.close()
4312 except IOError as why: 4467 except IOError as why:
4313 E5MessageBox.critical(self.ui, 4468 E5MessageBox.critical(self.ui,
4314 self.trUtf8("Create Package List"), 4469 self.trUtf8("Create Package List"),
4315 self.trUtf8("""<p>The file <b>PKGLIST</b> could not be created.</p>""" 4470 self.trUtf8(
4316 """<p>Reason: {0}</p>""").format(str(why))) 4471 """<p>The file <b>PKGLIST</b> could not be created.</p>"""
4472 """<p>Reason: {0}</p>""").format(str(why)))
4317 return 4473 return
4318 4474
4319 if not "PKGLIST" in self.pdata["OTHERS"]: 4475 if not "PKGLIST" in self.pdata["OTHERS"]:
4320 self.appendFile("PKGLIST") 4476 self.appendFile("PKGLIST")
4321 4477
4335 4491
4336 if len(self.pdata["MAINSCRIPT"]) == 0 or \ 4492 if len(self.pdata["MAINSCRIPT"]) == 0 or \
4337 len(self.pdata["MAINSCRIPT"][0]) == 0: 4493 len(self.pdata["MAINSCRIPT"][0]) == 0:
4338 E5MessageBox.critical(self.ui, 4494 E5MessageBox.critical(self.ui,
4339 self.trUtf8("Create Plugin Archive"), 4495 self.trUtf8("Create Plugin Archive"),
4340 self.trUtf8("""The project does not have a main script defined. """ 4496 self.trUtf8(
4341 """Aborting...""")) 4497 """The project does not have a main script defined. """
4498 """Aborting..."""))
4342 return 4499 return
4343 4500
4344 try: 4501 try:
4345 pkglistFile = open(pkglist, "r", encoding="utf-8") 4502 pkglistFile = open(pkglist, "r", encoding="utf-8")
4346 names = pkglistFile.read() 4503 names = pkglistFile.read()
4347 pkglistFile.close() 4504 pkglistFile.close()
4348 names = sorted(names.splitlines()) 4505 names = sorted(names.splitlines())
4349 except IOError as why: 4506 except IOError as why:
4350 E5MessageBox.critical(self.ui, 4507 E5MessageBox.critical(self.ui,
4351 self.trUtf8("Create Plugin Archive"), 4508 self.trUtf8("Create Plugin Archive"),
4352 self.trUtf8("""<p>The file <b>PKGLIST</b> could not be read.</p>""" 4509 self.trUtf8(
4353 """<p>Reason: {0}</p>""").format(str(why))) 4510 """<p>The file <b>PKGLIST</b> could not be read.</p>"""
4511 """<p>Reason: {0}</p>""").format(str(why)))
4354 return 4512 return
4355 4513
4356 archive = \ 4514 archive = os.path.join(
4357 os.path.join(self.ppath, self.pdata["MAINSCRIPT"][0].replace(".py", ".zip")) 4515 self.ppath, self.pdata["MAINSCRIPT"][0].replace(".py", ".zip"))
4358 try: 4516 try:
4359 archiveFile = zipfile.ZipFile(archive, "w") 4517 archiveFile = zipfile.ZipFile(archive, "w")
4360 except IOError as why: 4518 except IOError as why:
4361 E5MessageBox.critical(self.ui, 4519 E5MessageBox.critical(self.ui,
4362 self.trUtf8("Create Plugin Archive"), 4520 self.trUtf8("Create Plugin Archive"),
4363 self.trUtf8("""<p>The eric5 plugin archive file <b>{0}</b> could """ 4521 self.trUtf8(
4364 """not be created.</p>""" 4522 """<p>The eric5 plugin archive file <b>{0}</b> could """
4365 """<p>Reason: {1}</p>""").format(archive, str(why))) 4523 """not be created.</p>"""
4524 """<p>Reason: {1}</p>""").format(archive, str(why)))
4366 return 4525 return
4367 4526
4368 for name in names: 4527 for name in names:
4369 if name: 4528 if name:
4370 try: 4529 try:
4371 self.__createZipDirEntries(os.path.split(name)[0], archiveFile) 4530 self.__createZipDirEntries(
4531 os.path.split(name)[0], archiveFile)
4372 if snapshot and name == self.pdata["MAINSCRIPT"][0]: 4532 if snapshot and name == self.pdata["MAINSCRIPT"][0]:
4373 snapshotSource, version = self.__createSnapshotSource( 4533 snapshotSource, version = self.__createSnapshotSource(
4374 os.path.join(self.ppath, self.pdata["MAINSCRIPT"][0])) 4534 os.path.join(self.ppath,
4535 self.pdata["MAINSCRIPT"][0]))
4375 archiveFile.writestr(name, snapshotSource) 4536 archiveFile.writestr(name, snapshotSource)
4376 else: 4537 else:
4377 archiveFile.write(os.path.join(self.ppath, name), name) 4538 archiveFile.write(os.path.join(self.ppath, name), name)
4378 if name == self.pdata["MAINSCRIPT"][0]: 4539 if name == self.pdata["MAINSCRIPT"][0]:
4379 version = self.__pluginExtractVersion( 4540 version = self.__pluginExtractVersion(
4380 os.path.join(self.ppath, self.pdata["MAINSCRIPT"][0])) 4541 os.path.join(self.ppath,
4542 self.pdata["MAINSCRIPT"][0]))
4381 except OSError as why: 4543 except OSError as why:
4382 E5MessageBox.critical(self.ui, 4544 E5MessageBox.critical(self.ui,
4383 self.trUtf8("Create Plugin Archive"), 4545 self.trUtf8("Create Plugin Archive"),
4384 self.trUtf8("""<p>The file <b>{0}</b> could not be stored """ 4546 self.trUtf8(
4385 """in the archive. Ignoring it.</p>""" 4547 """<p>The file <b>{0}</b> could not be stored """
4386 """<p>Reason: {1}</p>""")\ 4548 """in the archive. Ignoring it.</p>"""
4387 .format(os.path.join(self.ppath, name), str(why))) 4549 """<p>Reason: {1}</p>""")\
4550 .format(os.path.join(self.ppath, name), str(why)))
4388 archiveFile.writestr("VERSION", version.encode("utf-8")) 4551 archiveFile.writestr("VERSION", version.encode("utf-8"))
4389 archiveFile.close() 4552 archiveFile.close()
4390 4553
4391 if not archive in self.pdata["OTHERS"]: 4554 if not archive in self.pdata["OTHERS"]:
4392 self.appendFile(archive) 4555 self.appendFile(archive)
4393 4556
4394 if self.ui.notificationsEnabled(): 4557 if self.ui.notificationsEnabled():
4395 self.ui.showNotification(UI.PixmapCache.getPixmap("pluginArchive48.png"), 4558 self.ui.showNotification(
4559 UI.PixmapCache.getPixmap("pluginArchive48.png"),
4396 self.trUtf8("Create Plugin Archive"), 4560 self.trUtf8("Create Plugin Archive"),
4397 self.trUtf8("""<p>The eric5 plugin archive file <b>{0}</b> was """ 4561 self.trUtf8(
4398 """created successfully.</p>""")\ 4562 """<p>The eric5 plugin archive file <b>{0}</b> was """
4563 """created successfully.</p>""")\
4399 .format(os.path.basename(archive))) 4564 .format(os.path.basename(archive)))
4400 else: 4565 else:
4401 E5MessageBox.information(self.ui, 4566 E5MessageBox.information(self.ui,
4402 self.trUtf8("Create Plugin Archive"), 4567 self.trUtf8("Create Plugin Archive"),
4403 self.trUtf8("""<p>The eric5 plugin archive file <b>{0}</b> was """ 4568 self.trUtf8(
4404 """created successfully.</p>""").format(archive)) 4569 """<p>The eric5 plugin archive file <b>{0}</b> was """
4570 """created successfully.</p>""").format(archive))
4405 4571
4406 def __pluginCreateSnapshotArchive(self): 4572 def __pluginCreateSnapshotArchive(self):
4407 """ 4573 """
4408 Private slot to create an eric5 plugin archive snapshot release. 4574 Private slot to create an eric5 plugin archive snapshot release.
4409 """ 4575 """
4443 except (IOError, UnicodeError) as why: 4609 except (IOError, UnicodeError) as why:
4444 E5MessageBox.critical(self.ui, 4610 E5MessageBox.critical(self.ui,
4445 self.trUtf8("Create Plugin Archive"), 4611 self.trUtf8("Create Plugin Archive"),
4446 self.trUtf8("""<p>The plugin file <b>{0}</b> could """ 4612 self.trUtf8("""<p>The plugin file <b>{0}</b> could """
4447 """not be read.</p>""" 4613 """not be read.</p>"""
4448 """<p>Reason: {1}</p>""").format(filename, str(why))) 4614 """<p>Reason: {1}</p>""")
4615 .format(filename, str(why)))
4449 return b"", "" 4616 return b"", ""
4450 4617
4451 lineno = 0 4618 lineno = 0
4452 while lineno < len(sourcelines): 4619 while lineno < len(sourcelines):
4453 if sourcelines[lineno].startswith("version = "): 4620 if sourcelines[lineno].startswith("version = "):
4454 # found the line to modify 4621 # found the line to modify
4455 datestr = time.strftime("%Y%m%d") 4622 datestr = time.strftime("%Y%m%d")
4456 lineend = sourcelines[lineno].replace(sourcelines[lineno].rstrip(), "") 4623 lineend = sourcelines[lineno]\
4457 sversion = "{0}-snapshot-{1}".format( 4624 .replace(sourcelines[lineno].rstrip(), "")
4458 sourcelines[lineno].replace("version = ", "").strip()[1:-1], 4625 sversion = "{0}-snapshot-{1}".format(sourcelines[lineno]\
4626 .replace("version = ", "").strip()[1:-1],
4459 datestr) 4627 datestr)
4460 sourcelines[lineno] = '{0} + "-snapshot-{1}"{2}'.format( 4628 sourcelines[lineno] = '{0} + "-snapshot-{1}"{2}'.format(
4461 sourcelines[lineno].rstrip(), datestr, lineend) 4629 sourcelines[lineno].rstrip(), datestr, lineend)
4462 break 4630 break
4463 4631
4478 sourcelines = Utilities.readEncodedFile(filename)[0] 4646 sourcelines = Utilities.readEncodedFile(filename)[0]
4479 sourcelines = sourcelines.splitlines(True) 4647 sourcelines = sourcelines.splitlines(True)
4480 except (IOError, UnicodeError) as why: 4648 except (IOError, UnicodeError) as why:
4481 E5MessageBox.critical(self.ui, 4649 E5MessageBox.critical(self.ui,
4482 self.trUtf8("Create Plugin Archive"), 4650 self.trUtf8("Create Plugin Archive"),
4483 self.trUtf8("""<p>The plugin file <b>{0}</b> could """ 4651 self.trUtf8(
4484 """not be read.</p>""" 4652 """<p>The plugin file <b>{0}</b> could """
4485 """<p>Reason: {1}</p>""").format(filename, str(why))) 4653 """not be read.</p> <p>Reason: {1}</p>""")
4654 .format(filename, str(why)))
4486 return "" 4655 return ""
4487 4656
4488 for sourceline in sourcelines: 4657 for sourceline in sourcelines:
4489 if sourceline.startswith("version = "): 4658 if sourceline.startswith("version = "):
4490 version = sourceline.replace("version = ", "").strip()\ 4659 version = sourceline.replace("version = ", "").strip()\

eric ide

mercurial