9220:e9e7eca7efee | 9221:bf71ee032bb4 |
---|---|
16 import zipfile | 16 import zipfile |
17 import contextlib | 17 import contextlib |
18 import pathlib | 18 import pathlib |
19 | 19 |
20 from PyQt6.QtCore import ( | 20 from PyQt6.QtCore import ( |
21 pyqtSlot, QFile, pyqtSignal, QCryptographicHash, QIODevice, QByteArray, | 21 pyqtSlot, |
22 QObject, QProcess | 22 QFile, |
23 pyqtSignal, | |
24 QCryptographicHash, | |
25 QIODevice, | |
26 QByteArray, | |
27 QObject, | |
28 QProcess, | |
23 ) | 29 ) |
24 from PyQt6.QtGui import QKeySequence, QAction | 30 from PyQt6.QtGui import QKeySequence, QAction |
25 from PyQt6.QtWidgets import ( | 31 from PyQt6.QtWidgets import QLineEdit, QToolBar, QDialog, QInputDialog, QMenu |
26 QLineEdit, QToolBar, QDialog, QInputDialog, QMenu | |
27 ) | |
28 from PyQt6.Qsci import QsciScintilla | 32 from PyQt6.Qsci import QsciScintilla |
29 | 33 |
30 from EricWidgets.EricApplication import ericApp | 34 from EricWidgets.EricApplication import ericApp |
31 from EricWidgets import EricFileDialog, EricMessageBox | 35 from EricWidgets import EricFileDialog, EricMessageBox |
32 from EricWidgets.EricListSelectionDialog import EricListSelectionDialog | 36 from EricWidgets.EricListSelectionDialog import EricListSelectionDialog |
56 | 60 |
57 | 61 |
58 class Project(QObject): | 62 class Project(QObject): |
59 """ | 63 """ |
60 Class implementing the project management functionality. | 64 Class implementing the project management functionality. |
61 | 65 |
62 @signal dirty(bool) emitted when the dirty state changes | 66 @signal dirty(bool) emitted when the dirty state changes |
63 @signal projectLanguageAdded(str) emitted after a new language was added | 67 @signal projectLanguageAdded(str) emitted after a new language was added |
64 @signal projectLanguageAddedByCode(str) emitted after a new language was | 68 @signal projectLanguageAddedByCode(str) emitted after a new language was |
65 added. The language code is sent by this signal. | 69 added. The language code is sent by this signal. |
66 @signal projectLanguageRemoved(str) emitted after a language was removed | 70 @signal projectLanguageRemoved(str) emitted after a language was removed |
123 @signal appendStdout(str) emitted after something was received from | 127 @signal appendStdout(str) emitted after something was received from |
124 a QProcess on stdout | 128 a QProcess on stdout |
125 @signal appendStderr(str) emitted after something was received from | 129 @signal appendStderr(str) emitted after something was received from |
126 a QProcess on stderr | 130 a QProcess on stderr |
127 """ | 131 """ |
132 | |
128 dirty = pyqtSignal(bool) | 133 dirty = pyqtSignal(bool) |
129 projectLanguageAdded = pyqtSignal(str) | 134 projectLanguageAdded = pyqtSignal(str) |
130 projectLanguageAddedByCode = pyqtSignal(str) | 135 projectLanguageAddedByCode = pyqtSignal(str) |
131 projectLanguageRemoved = pyqtSignal(str) | 136 projectLanguageRemoved = pyqtSignal(str) |
132 projectFormAdded = pyqtSignal(str) | 137 projectFormAdded = pyqtSignal(str) |
166 showMenu = pyqtSignal(str, QMenu) | 171 showMenu = pyqtSignal(str, QMenu) |
167 lexerAssociationsChanged = pyqtSignal() | 172 lexerAssociationsChanged = pyqtSignal() |
168 projectChanged = pyqtSignal() | 173 projectChanged = pyqtSignal() |
169 appendStdout = pyqtSignal(str) | 174 appendStdout = pyqtSignal(str) |
170 appendStderr = pyqtSignal(str) | 175 appendStderr = pyqtSignal(str) |
171 | 176 |
172 eols = [os.linesep, "\n", "\r", "\r\n"] | 177 eols = [os.linesep, "\n", "\r", "\r\n"] |
173 | 178 |
174 DefaultMake = "make" | 179 DefaultMake = "make" |
175 DefaultMakefile = "makefile" | 180 DefaultMakefile = "makefile" |
176 | 181 |
177 def __init__(self, parent=None, filename=None): | 182 def __init__(self, parent=None, filename=None): |
178 """ | 183 """ |
179 Constructor | 184 Constructor |
180 | 185 |
181 @param parent parent widget (usually the ui object) (QWidget) | 186 @param parent parent widget (usually the ui object) (QWidget) |
182 @param filename optional filename of a project file to open (string) | 187 @param filename optional filename of a project file to open (string) |
183 """ | 188 """ |
184 super().__init__(parent) | 189 super().__init__(parent) |
185 | 190 |
186 self.ui = parent | 191 self.ui = parent |
187 | 192 |
188 self.__progLanguages = [ | 193 self.__progLanguages = [ |
189 "Python3", | 194 "Python3", |
190 "MicroPython", | 195 "MicroPython", |
191 "Ruby", | 196 "Ruby", |
192 "JavaScript", | 197 "JavaScript", |
193 ] | 198 ] |
194 | 199 |
195 self.__dbgFilters = { | 200 self.__dbgFilters = { |
196 "Python3": self.tr( | 201 "Python3": self.tr( |
197 "Python3 Files (*.py *.py3);;" | 202 "Python3 Files (*.py *.py3);;" "Python3 GUI Files (*.pyw *.pyw3);;" |
198 "Python3 GUI Files (*.pyw *.pyw3);;"), | 203 ), |
199 } | 204 } |
200 | 205 |
201 self.vcsMenu = None | 206 self.vcsMenu = None |
202 self.__makeProcess = None | 207 self.__makeProcess = None |
203 | 208 |
204 self.__initProjectTypes() | 209 self.__initProjectTypes() |
205 | 210 |
206 self.__initData() | 211 self.__initData() |
207 | 212 |
208 self.__projectFile = ProjectFile(self) | 213 self.__projectFile = ProjectFile(self) |
209 self.__userProjectFile = UserProjectFile(self) | 214 self.__userProjectFile = UserProjectFile(self) |
210 self.__debuggerPropertiesFile = DebuggerPropertiesFile(self) | 215 self.__debuggerPropertiesFile = DebuggerPropertiesFile(self) |
211 self.__sessionFile = SessionFile(False) | 216 self.__sessionFile = SessionFile(False) |
212 self.__tasksFile = TasksFile(False) | 217 self.__tasksFile = TasksFile(False) |
213 | 218 |
214 self.recent = [] | 219 self.recent = [] |
215 self.__loadRecent() | 220 self.__loadRecent() |
216 | 221 |
217 if filename is not None: | 222 if filename is not None: |
218 self.openProject(filename) | 223 self.openProject(filename) |
219 else: | 224 else: |
220 self.vcs = self.initVCS() | 225 self.vcs = self.initVCS() |
221 | 226 |
222 from .ProjectBrowserModel import ProjectBrowserModel | 227 from .ProjectBrowserModel import ProjectBrowserModel |
228 | |
223 self.__model = ProjectBrowserModel(self) | 229 self.__model = ProjectBrowserModel(self) |
224 | 230 |
225 self.codemetrics = None | 231 self.codemetrics = None |
226 self.codecoverage = None | 232 self.codecoverage = None |
227 self.profiledata = None | 233 self.profiledata = None |
228 self.applicationDiagram = None | 234 self.applicationDiagram = None |
229 self.loadedDiagram = None | 235 self.loadedDiagram = None |
230 self.__findProjectFileDialog = None | 236 self.__findProjectFileDialog = None |
231 | 237 |
232 def __sourceExtensions(self, language): | 238 def __sourceExtensions(self, language): |
233 """ | 239 """ |
234 Private method to get the source extensions of a programming language. | 240 Private method to get the source extensions of a programming language. |
235 | 241 |
236 @param language programming language (string) | 242 @param language programming language (string) |
237 @return source extensions (list of string) | 243 @return source extensions (list of string) |
238 """ | 244 """ |
239 if language == "Python3": | 245 if language == "Python3": |
240 extensions = Preferences.getPython("Python3Extensions") | 246 extensions = Preferences.getPython("Python3Extensions") |
252 return extensions | 258 return extensions |
253 else: | 259 else: |
254 return { | 260 return { |
255 "Ruby": [".rb"], | 261 "Ruby": [".rb"], |
256 "JavaScript": [".js"], | 262 "JavaScript": [".js"], |
257 "Mixed": ( | 263 "Mixed": (Preferences.getPython("Python3Extensions") + [".rb", ".js"]), |
258 Preferences.getPython("Python3Extensions") + | |
259 ['.rb', '.js']), | |
260 }.get(language, "") | 264 }.get(language, "") |
261 | 265 |
262 def getProgrammingLanguages(self): | 266 def getProgrammingLanguages(self): |
263 """ | 267 """ |
264 Public method to get the programming languages supported by project. | 268 Public method to get the programming languages supported by project. |
265 | 269 |
266 @return list of supported programming languages (list of string) | 270 @return list of supported programming languages (list of string) |
267 """ | 271 """ |
268 return self.__progLanguages[:] | 272 return self.__progLanguages[:] |
269 | 273 |
270 def getDebuggerFilters(self, language): | 274 def getDebuggerFilters(self, language): |
271 """ | 275 """ |
272 Public method to get the debugger filters for a programming language. | 276 Public method to get the debugger filters for a programming language. |
273 | 277 |
274 @param language programming language | 278 @param language programming language |
275 @type str | 279 @type str |
276 @return filter string | 280 @return filter string |
277 @rtype str | 281 @rtype str |
278 """ | 282 """ |
279 try: | 283 try: |
280 return self.__dbgFilters[language] | 284 return self.__dbgFilters[language] |
281 except KeyError: | 285 except KeyError: |
282 return "" | 286 return "" |
283 | 287 |
284 def __initProjectTypes(self): | 288 def __initProjectTypes(self): |
285 """ | 289 """ |
286 Private method to initialize the list of supported project types. | 290 Private method to initialize the list of supported project types. |
287 """ | 291 """ |
288 self.__fileTypeCallbacks = {} | 292 self.__fileTypeCallbacks = {} |
289 self.__lexerAssociationCallbacks = {} | 293 self.__lexerAssociationCallbacks = {} |
290 self.__binaryTranslationsCallbacks = {} | 294 self.__binaryTranslationsCallbacks = {} |
291 | 295 |
292 self.__projectTypes = { | 296 self.__projectTypes = { |
293 "PyQt5": self.tr("PyQt5 GUI"), | 297 "PyQt5": self.tr("PyQt5 GUI"), |
294 "PyQt5C": self.tr("PyQt5 Console"), | 298 "PyQt5C": self.tr("PyQt5 Console"), |
295 "PyQt6": self.tr("PyQt6 GUI"), | 299 "PyQt6": self.tr("PyQt6 GUI"), |
296 "PyQt6C": self.tr("PyQt6 Console"), | 300 "PyQt6C": self.tr("PyQt6 Console"), |
297 "E7Plugin": self.tr("Eric7 Plugin"), | 301 "E7Plugin": self.tr("Eric7 Plugin"), |
298 "Console": self.tr("Console"), | 302 "Console": self.tr("Console"), |
299 "Other": self.tr("Other"), | 303 "Other": self.tr("Other"), |
300 } | 304 } |
301 | 305 |
302 self.__projectProgLanguages = { | 306 self.__projectProgLanguages = { |
303 "Python3": ["PyQt5", "PyQt5C", "PyQt6", "PyQt6C", "E7Plugin", | 307 "Python3": [ |
304 "Console", "Other"], | 308 "PyQt5", |
309 "PyQt5C", | |
310 "PyQt6", | |
311 "PyQt6C", | |
312 "E7Plugin", | |
313 "Console", | |
314 "Other", | |
315 ], | |
305 "MicroPython": ["Console", "Other"], | 316 "MicroPython": ["Console", "Other"], |
306 "Ruby": ["Console", "Other"], | 317 "Ruby": ["Console", "Other"], |
307 "JavaScript": ["Other"], | 318 "JavaScript": ["Other"], |
308 } | 319 } |
309 | 320 |
310 if Utilities.checkPyside(variant=2): | 321 if Utilities.checkPyside(variant=2): |
311 self.__projectTypes["PySide2"] = self.tr("PySide2 GUI") | 322 self.__projectTypes["PySide2"] = self.tr("PySide2 GUI") |
312 self.__projectTypes["PySide2C"] = self.tr("PySide2 Console") | 323 self.__projectTypes["PySide2C"] = self.tr("PySide2 Console") |
313 self.__projectProgLanguages["Python3"].extend( | 324 self.__projectProgLanguages["Python3"].extend(["PySide2", "PySide2C"]) |
314 ["PySide2", "PySide2C"]) | 325 |
315 | |
316 if Utilities.checkPyside(variant=6): | 326 if Utilities.checkPyside(variant=6): |
317 self.__projectTypes["PySide6"] = self.tr("PySide6 GUI") | 327 self.__projectTypes["PySide6"] = self.tr("PySide6 GUI") |
318 self.__projectTypes["PySide6C"] = self.tr("PySide6 Console") | 328 self.__projectTypes["PySide6C"] = self.tr("PySide6 Console") |
319 self.__projectProgLanguages["Python3"].extend( | 329 self.__projectProgLanguages["Python3"].extend(["PySide6", "PySide6C"]) |
320 ["PySide6", "PySide6C"]) | 330 |
321 | |
322 def getProjectTypes(self, progLanguage=""): | 331 def getProjectTypes(self, progLanguage=""): |
323 """ | 332 """ |
324 Public method to get the list of supported project types. | 333 Public method to get the list of supported project types. |
325 | 334 |
326 @param progLanguage programming language to get project types for | 335 @param progLanguage programming language to get project types for |
327 (string) | 336 (string) |
328 @return reference to the dictionary of project types. | 337 @return reference to the dictionary of project types. |
329 """ | 338 """ |
330 if progLanguage and progLanguage in self.__projectProgLanguages: | 339 if progLanguage and progLanguage in self.__projectProgLanguages: |
332 for ptype in self.__projectProgLanguages[progLanguage]: | 341 for ptype in self.__projectProgLanguages[progLanguage]: |
333 ptypes[ptype] = self.__projectTypes[ptype] | 342 ptypes[ptype] = self.__projectTypes[ptype] |
334 return ptypes | 343 return ptypes |
335 else: | 344 else: |
336 return self.__projectTypes | 345 return self.__projectTypes |
337 | 346 |
338 def hasProjectType(self, type_, progLanguage=""): | 347 def hasProjectType(self, type_, progLanguage=""): |
339 """ | 348 """ |
340 Public method to check, if a project type is already registered. | 349 Public method to check, if a project type is already registered. |
341 | 350 |
342 @param type_ internal type designator (string) | 351 @param type_ internal type designator (string) |
343 @param progLanguage programming language of the project type (string) | 352 @param progLanguage programming language of the project type (string) |
344 @return flag indicating presence of the project type (boolean) | 353 @return flag indicating presence of the project type (boolean) |
345 """ | 354 """ |
346 if progLanguage: | 355 if progLanguage: |
347 return ( | 356 return ( |
348 progLanguage in self.__projectProgLanguages and | 357 progLanguage in self.__projectProgLanguages |
349 type_ in self.__projectProgLanguages[progLanguage] | 358 and type_ in self.__projectProgLanguages[progLanguage] |
350 ) | 359 ) |
351 else: | 360 else: |
352 return type_ in self.__projectTypes | 361 return type_ in self.__projectTypes |
353 | 362 |
354 def registerProjectType(self, type_, description, fileTypeCallback=None, | 363 def registerProjectType( |
355 binaryTranslationsCallback=None, | 364 self, |
356 lexerAssociationCallback=None, progLanguages=None): | 365 type_, |
366 description, | |
367 fileTypeCallback=None, | |
368 binaryTranslationsCallback=None, | |
369 lexerAssociationCallback=None, | |
370 progLanguages=None, | |
371 ): | |
357 """ | 372 """ |
358 Public method to register a project type. | 373 Public method to register a project type. |
359 | 374 |
360 @param type_ internal type designator to be registered (string) | 375 @param type_ internal type designator to be registered (string) |
361 @param description more verbose type name (display string) (string) | 376 @param description more verbose type name (display string) (string) |
362 @param fileTypeCallback reference to a method returning a dictionary | 377 @param fileTypeCallback reference to a method returning a dictionary |
363 of filetype associations. | 378 of filetype associations. |
364 @param binaryTranslationsCallback reference to a method returning | 379 @param binaryTranslationsCallback reference to a method returning |
376 EricMessageBox.critical( | 391 EricMessageBox.critical( |
377 self.ui, | 392 self.ui, |
378 self.tr("Registering Project Type"), | 393 self.tr("Registering Project Type"), |
379 self.tr( | 394 self.tr( |
380 """<p>The Programming Language <b>{0}</b> is not""" | 395 """<p>The Programming Language <b>{0}</b> is not""" |
381 """ supported (project type: {1}).</p>""") | 396 """ supported (project type: {1}).</p>""" |
382 .format(progLanguage, type_) | 397 ).format(progLanguage, type_), |
383 ) | 398 ) |
384 return | 399 return |
385 | 400 |
386 if type_ in self.__projectProgLanguages[progLanguage]: | 401 if type_ in self.__projectProgLanguages[progLanguage]: |
387 EricMessageBox.critical( | 402 EricMessageBox.critical( |
388 self.ui, | 403 self.ui, |
389 self.tr("Registering Project Type"), | 404 self.tr("Registering Project Type"), |
390 self.tr( | 405 self.tr( |
391 """<p>The Project type <b>{0}</b> is already""" | 406 """<p>The Project type <b>{0}</b> is already""" |
392 """ registered with Programming Language""" | 407 """ registered with Programming Language""" |
393 """ <b>{1}</b>.</p>""") | 408 """ <b>{1}</b>.</p>""" |
394 .format(type_, progLanguage) | 409 ).format(type_, progLanguage), |
395 ) | 410 ) |
396 return | 411 return |
397 | 412 |
398 if type_ in self.__projectTypes: | 413 if type_ in self.__projectTypes: |
399 EricMessageBox.critical( | 414 EricMessageBox.critical( |
400 self.ui, | 415 self.ui, |
401 self.tr("Registering Project Type"), | 416 self.tr("Registering Project Type"), |
402 self.tr("""<p>The Project type <b>{0}</b> is already""" | 417 self.tr( |
403 """ registered.</p>""").format(type_) | 418 """<p>The Project type <b>{0}</b> is already""" |
419 """ registered.</p>""" | |
420 ).format(type_), | |
404 ) | 421 ) |
405 else: | 422 else: |
406 self.__projectTypes[type_] = description | 423 self.__projectTypes[type_] = description |
407 self.__fileTypeCallbacks[type_] = fileTypeCallback | 424 self.__fileTypeCallbacks[type_] = fileTypeCallback |
408 self.__lexerAssociationCallbacks[type_] = lexerAssociationCallback | 425 self.__lexerAssociationCallbacks[type_] = lexerAssociationCallback |
409 self.__binaryTranslationsCallbacks[type_] = ( | 426 self.__binaryTranslationsCallbacks[type_] = binaryTranslationsCallback |
410 binaryTranslationsCallback | |
411 ) | |
412 if progLanguages: | 427 if progLanguages: |
413 for progLanguage in progLanguages: | 428 for progLanguage in progLanguages: |
414 self.__projectProgLanguages[progLanguage].append(type_) | 429 self.__projectProgLanguages[progLanguage].append(type_) |
415 else: | 430 else: |
416 # no specific programming languages given -> add to all | 431 # no specific programming languages given -> add to all |
417 for progLanguage in self.__projectProgLanguages: | 432 for progLanguage in self.__projectProgLanguages: |
418 self.__projectProgLanguages[progLanguage].append(type_) | 433 self.__projectProgLanguages[progLanguage].append(type_) |
419 | 434 |
420 def unregisterProjectType(self, type_): | 435 def unregisterProjectType(self, type_): |
421 """ | 436 """ |
422 Public method to unregister a project type. | 437 Public method to unregister a project type. |
423 | 438 |
424 @param type_ internal type designator to be unregistered (string) | 439 @param type_ internal type designator to be unregistered (string) |
425 """ | 440 """ |
426 for progLanguage in self.__projectProgLanguages: | 441 for progLanguage in self.__projectProgLanguages: |
427 if type_ in self.__projectProgLanguages[progLanguage]: | 442 if type_ in self.__projectProgLanguages[progLanguage]: |
428 self.__projectProgLanguages[progLanguage].remove(type_) | 443 self.__projectProgLanguages[progLanguage].remove(type_) |
432 del self.__fileTypeCallbacks[type_] | 447 del self.__fileTypeCallbacks[type_] |
433 if type_ in self.__lexerAssociationCallbacks: | 448 if type_ in self.__lexerAssociationCallbacks: |
434 del self.__lexerAssociationCallbacks[type_] | 449 del self.__lexerAssociationCallbacks[type_] |
435 if type_ in self.__binaryTranslationsCallbacks: | 450 if type_ in self.__binaryTranslationsCallbacks: |
436 del self.__binaryTranslationsCallbacks[type_] | 451 del self.__binaryTranslationsCallbacks[type_] |
437 | 452 |
438 def __initData(self): | 453 def __initData(self): |
439 """ | 454 """ |
440 Private method to initialize the project data part. | 455 Private method to initialize the project data part. |
441 """ | 456 """ |
442 self.loaded = False # flag for the loaded status | 457 self.loaded = False # flag for the loaded status |
443 self.__dirty = False # dirty flag | 458 self.__dirty = False # dirty flag |
444 self.pfile = "" # name of the project file | 459 self.pfile = "" # name of the project file |
445 self.ppath = "" # name of the project directory | 460 self.ppath = "" # name of the project directory |
446 self.translationsRoot = "" # the translations prefix | 461 self.translationsRoot = "" # the translations prefix |
447 self.name = "" | 462 self.name = "" |
448 self.opened = False | 463 self.opened = False |
449 self.subdirs = [] | 464 self.subdirs = [] |
450 # record the project dir as a relative path (i.e. empty path) | 465 # record the project dir as a relative path (i.e. empty path) |
451 self.otherssubdirs = [] | 466 self.otherssubdirs = [] |
452 self.vcs = None | 467 self.vcs = None |
453 self.vcsRequested = False | 468 self.vcsRequested = False |
454 self.dbgVirtualEnv = '' | 469 self.dbgVirtualEnv = "" |
455 self.dbgCmdline = '' | 470 self.dbgCmdline = "" |
456 self.dbgWd = '' | 471 self.dbgWd = "" |
457 self.dbgEnv = '' | 472 self.dbgEnv = "" |
458 self.dbgReportExceptions = True | 473 self.dbgReportExceptions = True |
459 self.dbgExcList = [] | 474 self.dbgExcList = [] |
460 self.dbgExcIgnoreList = [] | 475 self.dbgExcIgnoreList = [] |
461 self.dbgAutoClearShell = True | 476 self.dbgAutoClearShell = True |
462 self.dbgTracePython = False | 477 self.dbgTracePython = False |
465 self.dbgMultiprocessNoDebug = "" | 480 self.dbgMultiprocessNoDebug = "" |
466 self.dbgGlobalConfigOverride = { | 481 self.dbgGlobalConfigOverride = { |
467 "enable": False, | 482 "enable": False, |
468 "redirect": True, | 483 "redirect": True, |
469 } | 484 } |
470 | 485 |
471 self.pdata = { | 486 self.pdata = { |
472 "DESCRIPTION": "", | 487 "DESCRIPTION": "", |
473 "VERSION": "", | 488 "VERSION": "", |
474 "SOURCES": [], | 489 "SOURCES": [], |
475 "FORMS": [], | 490 "FORMS": [], |
483 "TRANSLATIONSBINPATH": "", | 498 "TRANSLATIONSBINPATH": "", |
484 "MAINSCRIPT": "", | 499 "MAINSCRIPT": "", |
485 "VCS": "None", | 500 "VCS": "None", |
486 "VCSOPTIONS": {}, | 501 "VCSOPTIONS": {}, |
487 "VCSOTHERDATA": {}, | 502 "VCSOTHERDATA": {}, |
488 "AUTHOR": '', | 503 "AUTHOR": "", |
489 "EMAIL": '', | 504 "EMAIL": "", |
490 "HASH": '', | 505 "HASH": "", |
491 "PROGLANGUAGE": "Python3", | 506 "PROGLANGUAGE": "Python3", |
492 "MIXEDLANGUAGE": False, | 507 "MIXEDLANGUAGE": False, |
493 "PROJECTTYPE": "PyQt5", | 508 "PROJECTTYPE": "PyQt5", |
494 "SPELLLANGUAGE": | 509 "SPELLLANGUAGE": Preferences.getEditor("SpellCheckingDefaultLanguage"), |
495 Preferences.getEditor("SpellCheckingDefaultLanguage"), | 510 "SPELLWORDS": "", |
496 "SPELLWORDS": '', | 511 "SPELLEXCLUDES": "", |
497 "SPELLEXCLUDES": '', | |
498 "FILETYPES": {}, | 512 "FILETYPES": {}, |
499 "LEXERASSOCS": {}, | 513 "LEXERASSOCS": {}, |
500 "PROJECTTYPESPECIFICDATA": {}, | 514 "PROJECTTYPESPECIFICDATA": {}, |
501 "CHECKERSPARMS": {}, | 515 "CHECKERSPARMS": {}, |
502 "PACKAGERSPARMS": {}, | 516 "PACKAGERSPARMS": {}, |
519 "Package": "", | 533 "Package": "", |
520 "RcSuffix": "", | 534 "RcSuffix": "", |
521 "PackagesRoot": "", | 535 "PackagesRoot": "", |
522 }, | 536 }, |
523 "RCCPARAMS": { | 537 "RCCPARAMS": { |
524 "CompressionThreshold": 70, # default value | 538 "CompressionThreshold": 70, # default value |
525 "CompressLevel": 0, # use zlib default | 539 "CompressLevel": 0, # use zlib default |
526 "CompressionDisable": False, | 540 "CompressionDisable": False, |
527 "PathPrefix": "", | 541 "PathPrefix": "", |
528 }, | 542 }, |
529 "EOL": -1, | 543 "EOL": -1, |
530 "DOCSTRING": "", | 544 "DOCSTRING": "", |
531 "TESTING_FRAMEWORK": "", | 545 "TESTING_FRAMEWORK": "", |
532 "LICENSE": "", | 546 "LICENSE": "", |
533 } | 547 } |
534 | 548 |
535 self.__initDebugProperties() | 549 self.__initDebugProperties() |
536 | 550 |
537 self.pudata = { | 551 self.pudata = { |
538 "VCSOVERRIDE": "", | 552 "VCSOVERRIDE": "", |
539 "VCSSTATUSMONITORINTERVAL": 0, | 553 "VCSSTATUSMONITORINTERVAL": 0, |
540 } | 554 } |
541 | 555 |
542 self.vcs = self.initVCS() | 556 self.vcs = self.initVCS() |
543 | 557 |
544 def getData(self, category, key): | 558 def getData(self, category, key): |
545 """ | 559 """ |
546 Public method to get data out of the project data store. | 560 Public method to get data out of the project data store. |
547 | 561 |
548 @param category category of the data to get (string, one of | 562 @param category category of the data to get (string, one of |
549 PROJECTTYPESPECIFICDATA, CHECKERSPARMS, PACKAGERSPARMS, | 563 PROJECTTYPESPECIFICDATA, CHECKERSPARMS, PACKAGERSPARMS, |
550 DOCUMENTATIONPARMS or OTHERTOOLSPARMS) | 564 DOCUMENTATIONPARMS or OTHERTOOLSPARMS) |
551 @param key key of the data entry to get (string). | 565 @param key key of the data entry to get (string). |
552 @return a copy of the requested data or None | 566 @return a copy of the requested data or None |
553 """ | 567 """ |
554 # __IGNORE_WARNING_D202__ | 568 # __IGNORE_WARNING_D202__ |
555 if ( | 569 if ( |
556 category in ["PROJECTTYPESPECIFICDATA", "CHECKERSPARMS", | 570 category |
557 "PACKAGERSPARMS", "DOCUMENTATIONPARMS", | 571 in [ |
558 "OTHERTOOLSPARMS"] and | 572 "PROJECTTYPESPECIFICDATA", |
559 key in self.pdata[category] | 573 "CHECKERSPARMS", |
574 "PACKAGERSPARMS", | |
575 "DOCUMENTATIONPARMS", | |
576 "OTHERTOOLSPARMS", | |
577 ] | |
578 and key in self.pdata[category] | |
560 ): | 579 ): |
561 return copy.deepcopy(self.pdata[category][key]) | 580 return copy.deepcopy(self.pdata[category][key]) |
562 else: | 581 else: |
563 return None | 582 return None |
564 | 583 |
565 def setData(self, category, key, data): | 584 def setData(self, category, key, data): |
566 """ | 585 """ |
567 Public method to store data in the project data store. | 586 Public method to store data in the project data store. |
568 | 587 |
569 @param category category of the data to get (string, one of | 588 @param category category of the data to get (string, one of |
570 PROJECTTYPESPECIFICDATA, CHECKERSPARMS, PACKAGERSPARMS, | 589 PROJECTTYPESPECIFICDATA, CHECKERSPARMS, PACKAGERSPARMS, |
571 DOCUMENTATIONPARMS or OTHERTOOLSPARMS) | 590 DOCUMENTATIONPARMS or OTHERTOOLSPARMS) |
572 @param key key of the data entry to get (string). | 591 @param key key of the data entry to get (string). |
573 @param data data to be stored | 592 @param data data to be stored |
574 @return flag indicating success (boolean) | 593 @return flag indicating success (boolean) |
575 """ | 594 """ |
576 # __IGNORE_WARNING_D202__ | 595 # __IGNORE_WARNING_D202__ |
577 if category not in ["PROJECTTYPESPECIFICDATA", "CHECKERSPARMS", | 596 if category not in [ |
578 "PACKAGERSPARMS", "DOCUMENTATIONPARMS", | 597 "PROJECTTYPESPECIFICDATA", |
579 "OTHERTOOLSPARMS"]: | 598 "CHECKERSPARMS", |
599 "PACKAGERSPARMS", | |
600 "DOCUMENTATIONPARMS", | |
601 "OTHERTOOLSPARMS", | |
602 ]: | |
580 return False | 603 return False |
581 | 604 |
582 # test for changes of data and save them in the project | 605 # test for changes of data and save them in the project |
583 # 1. there were none, now there are | 606 # 1. there were none, now there are |
584 if key not in self.pdata[category] and len(data) > 0: | 607 if key not in self.pdata[category] and len(data) > 0: |
585 self.pdata[category][key] = copy.deepcopy(data) | 608 self.pdata[category][key] = copy.deepcopy(data) |
586 self.setDirty(True) | 609 self.setDirty(True) |
595 self.setDirty(True) | 618 self.setDirty(True) |
596 # 4. there were none and none are given | 619 # 4. there were none and none are given |
597 else: | 620 else: |
598 return False | 621 return False |
599 return True | 622 return True |
600 | 623 |
601 def initFileTypes(self): | 624 def initFileTypes(self): |
602 """ | 625 """ |
603 Public method to initialize the filetype associations with default | 626 Public method to initialize the filetype associations with default |
604 values. | 627 values. |
605 """ | 628 """ |
613 "*.epj": "OTHERS", | 636 "*.epj": "OTHERS", |
614 "GNUmakefile": "OTHERS", | 637 "GNUmakefile": "OTHERS", |
615 "makefile": "OTHERS", | 638 "makefile": "OTHERS", |
616 "Makefile": "OTHERS", | 639 "Makefile": "OTHERS", |
617 } | 640 } |
618 | 641 |
619 # Sources | 642 # Sources |
620 sourceKey = ( | 643 sourceKey = ( |
621 "Mixed" | 644 "Mixed" if self.pdata["MIXEDLANGUAGE"] else self.pdata["PROGLANGUAGE"] |
622 if self.pdata["MIXEDLANGUAGE"] else | |
623 self.pdata["PROGLANGUAGE"] | |
624 ) | 645 ) |
625 for ext in self.__sourceExtensions(sourceKey): | 646 for ext in self.__sourceExtensions(sourceKey): |
626 self.pdata["FILETYPES"]["*{0}".format(ext)] = "SOURCES" | 647 self.pdata["FILETYPES"]["*{0}".format(ext)] = "SOURCES" |
627 | 648 |
628 # IDL interfaces | 649 # IDL interfaces |
629 self.pdata["FILETYPES"]["*.idl"] = "INTERFACES" | 650 self.pdata["FILETYPES"]["*.idl"] = "INTERFACES" |
630 | 651 |
631 # Protobuf Files | 652 # Protobuf Files |
632 self.pdata["FILETYPES"]["*.proto"] = "PROTOCOLS" | 653 self.pdata["FILETYPES"]["*.proto"] = "PROTOCOLS" |
633 | 654 |
634 # Forms | 655 # Forms |
635 if self.pdata["PROJECTTYPE"] in ["E7Plugin", | 656 if self.pdata["PROJECTTYPE"] in [ |
636 "PyQt5", | 657 "E7Plugin", |
637 "PyQt6", | 658 "PyQt5", |
638 "PySide2", | 659 "PyQt6", |
639 "PySide6"]: | 660 "PySide2", |
661 "PySide6", | |
662 ]: | |
640 self.pdata["FILETYPES"]["*.ui"] = "FORMS" | 663 self.pdata["FILETYPES"]["*.ui"] = "FORMS" |
641 | 664 |
642 # Resources | 665 # Resources |
643 if self.pdata["PROJECTTYPE"] in ["PyQt5", "PyQt5C", | 666 if self.pdata["PROJECTTYPE"] in [ |
644 "PySide2", "PySide2C", | 667 "PyQt5", |
645 "PySide6", "PySide6C"]: | 668 "PyQt5C", |
669 "PySide2", | |
670 "PySide2C", | |
671 "PySide6", | |
672 "PySide6C", | |
673 ]: | |
646 self.pdata["FILETYPES"]["*.qrc"] = "RESOURCES" | 674 self.pdata["FILETYPES"]["*.qrc"] = "RESOURCES" |
647 | 675 |
648 # Translations | 676 # Translations |
649 if self.pdata["PROJECTTYPE"] in ["E7Plugin", | 677 if self.pdata["PROJECTTYPE"] in [ |
650 "PyQt5", "PyQt5C", | 678 "E7Plugin", |
651 "PyQt6", "PyQt6C", | 679 "PyQt5", |
652 "PySide2", "PySide2C", | 680 "PyQt5C", |
653 "PySide6", "PySide6C"]: | 681 "PyQt6", |
682 "PyQt6C", | |
683 "PySide2", | |
684 "PySide2C", | |
685 "PySide6", | |
686 "PySide6C", | |
687 ]: | |
654 self.pdata["FILETYPES"]["*.ts"] = "TRANSLATIONS" | 688 self.pdata["FILETYPES"]["*.ts"] = "TRANSLATIONS" |
655 self.pdata["FILETYPES"]["*.qm"] = "TRANSLATIONS" | 689 self.pdata["FILETYPES"]["*.qm"] = "TRANSLATIONS" |
656 | 690 |
657 # Project type specific ones | 691 # Project type specific ones |
658 with contextlib.suppress(KeyError): | 692 with contextlib.suppress(KeyError): |
659 if self.__fileTypeCallbacks[ | 693 if self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"]] is not None: |
660 self.pdata["PROJECTTYPE"]] is not None: | |
661 ftypes = self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"]]() | 694 ftypes = self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"]]() |
662 self.pdata["FILETYPES"].update(ftypes) | 695 self.pdata["FILETYPES"].update(ftypes) |
663 | 696 |
664 self.setDirty(True) | 697 self.setDirty(True) |
665 | 698 |
666 def updateFileTypes(self): | 699 def updateFileTypes(self): |
667 """ | 700 """ |
668 Public method to update the filetype associations with new default | 701 Public method to update the filetype associations with new default |
669 values. | 702 values. |
670 """ | 703 """ |
671 if self.pdata["PROJECTTYPE"] in ["E7Plugin", | 704 if self.pdata["PROJECTTYPE"] in [ |
672 "PyQt5", "PyQt5C", | 705 "E7Plugin", |
673 "PyQt6", "PyQt6C", | 706 "PyQt5", |
674 "PySide2", "PySide2C", | 707 "PyQt5C", |
675 "PySide6", "PySide6C"]: | 708 "PyQt6", |
709 "PyQt6C", | |
710 "PySide2", | |
711 "PySide2C", | |
712 "PySide6", | |
713 "PySide6C", | |
714 ]: | |
676 if "*.ts" not in self.pdata["FILETYPES"]: | 715 if "*.ts" not in self.pdata["FILETYPES"]: |
677 self.pdata["FILETYPES"]["*.ts"] = "TRANSLATIONS" | 716 self.pdata["FILETYPES"]["*.ts"] = "TRANSLATIONS" |
678 if "*.qm" not in self.pdata["FILETYPES"]: | 717 if "*.qm" not in self.pdata["FILETYPES"]: |
679 self.pdata["FILETYPES"]["*.qm"] = "TRANSLATIONS" | 718 self.pdata["FILETYPES"]["*.qm"] = "TRANSLATIONS" |
680 with contextlib.suppress(KeyError): | 719 with contextlib.suppress(KeyError): |
681 if self.__fileTypeCallbacks[ | 720 if self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"]] is not None: |
682 self.pdata["PROJECTTYPE"]] is not None: | |
683 ftypes = self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"]]() | 721 ftypes = self.__fileTypeCallbacks[self.pdata["PROJECTTYPE"]]() |
684 for pattern, ftype in list(ftypes.items()): | 722 for pattern, ftype in list(ftypes.items()): |
685 if pattern not in self.pdata["FILETYPES"]: | 723 if pattern not in self.pdata["FILETYPES"]: |
686 self.pdata["FILETYPES"][pattern] = ftype | 724 self.pdata["FILETYPES"][pattern] = ftype |
687 self.setDirty(True) | 725 self.setDirty(True) |
688 | 726 |
689 def __loadRecent(self): | 727 def __loadRecent(self): |
690 """ | 728 """ |
691 Private method to load the recently opened project filenames. | 729 Private method to load the recently opened project filenames. |
692 """ | 730 """ |
693 self.recent = [] | 731 self.recent = [] |
695 rp = Preferences.Prefs.rsettings.value(recentNameProject) | 733 rp = Preferences.Prefs.rsettings.value(recentNameProject) |
696 if rp is not None: | 734 if rp is not None: |
697 for f in rp: | 735 for f in rp: |
698 if pathlib.Path(f).exists(): | 736 if pathlib.Path(f).exists(): |
699 self.recent.append(f) | 737 self.recent.append(f) |
700 | 738 |
701 def __saveRecent(self): | 739 def __saveRecent(self): |
702 """ | 740 """ |
703 Private method to save the list of recently opened filenames. | 741 Private method to save the list of recently opened filenames. |
704 """ | 742 """ |
705 Preferences.Prefs.rsettings.setValue(recentNameProject, self.recent) | 743 Preferences.Prefs.rsettings.setValue(recentNameProject, self.recent) |
706 Preferences.Prefs.rsettings.sync() | 744 Preferences.Prefs.rsettings.sync() |
707 | 745 |
708 def getMostRecent(self): | 746 def getMostRecent(self): |
709 """ | 747 """ |
710 Public method to get the most recently opened project. | 748 Public method to get the most recently opened project. |
711 | 749 |
712 @return path of the most recently opened project (string) | 750 @return path of the most recently opened project (string) |
713 """ | 751 """ |
714 if len(self.recent): | 752 if len(self.recent): |
715 return self.recent[0] | 753 return self.recent[0] |
716 else: | 754 else: |
717 return None | 755 return None |
718 | 756 |
719 def getModel(self): | 757 def getModel(self): |
720 """ | 758 """ |
721 Public method to get a reference to the project browser model. | 759 Public method to get a reference to the project browser model. |
722 | 760 |
723 @return reference to the project browser model (ProjectBrowserModel) | 761 @return reference to the project browser model (ProjectBrowserModel) |
724 """ | 762 """ |
725 return self.__model | 763 return self.__model |
726 | 764 |
727 def startFileSystemMonitoring(self): | 765 def startFileSystemMonitoring(self): |
728 """ | 766 """ |
729 Public method to (re)start monitoring the project file system. | 767 Public method to (re)start monitoring the project file system. |
730 """ | 768 """ |
731 self.__model.startFileSystemMonitoring() | 769 self.__model.startFileSystemMonitoring() |
732 | 770 |
733 def stopFileSystemMonitoring(self): | 771 def stopFileSystemMonitoring(self): |
734 """ | 772 """ |
735 Public method to stop monitoring the project file system. | 773 Public method to stop monitoring the project file system. |
736 """ | 774 """ |
737 self.__model.stopFileSystemMonitoring() | 775 self.__model.stopFileSystemMonitoring() |
738 | 776 |
739 def getVcs(self): | 777 def getVcs(self): |
740 """ | 778 """ |
741 Public method to get a reference to the VCS object. | 779 Public method to get a reference to the VCS object. |
742 | 780 |
743 @return reference to the VCS object | 781 @return reference to the VCS object |
744 """ | 782 """ |
745 return self.vcs | 783 return self.vcs |
746 | 784 |
747 def handlePreferencesChanged(self): | 785 def handlePreferencesChanged(self): |
748 """ | 786 """ |
749 Public slot used to handle the preferencesChanged signal. | 787 Public slot used to handle the preferencesChanged signal. |
750 """ | 788 """ |
751 if self.pudata["VCSSTATUSMONITORINTERVAL"]: | 789 if self.pudata["VCSSTATUSMONITORINTERVAL"]: |
752 self.setStatusMonitorInterval( | 790 self.setStatusMonitorInterval(self.pudata["VCSSTATUSMONITORINTERVAL"]) |
753 self.pudata["VCSSTATUSMONITORINTERVAL"]) | |
754 else: | 791 else: |
755 self.setStatusMonitorInterval( | 792 self.setStatusMonitorInterval(Preferences.getVCS("StatusMonitorInterval")) |
756 Preferences.getVCS("StatusMonitorInterval")) | 793 |
757 | |
758 self.__model.preferencesChanged() | 794 self.__model.preferencesChanged() |
759 | 795 |
760 def setDirty(self, dirty): | 796 def setDirty(self, dirty): |
761 """ | 797 """ |
762 Public method to set the dirty state. | 798 Public method to set the dirty state. |
763 | 799 |
764 It emits the signal dirty(bool). | 800 It emits the signal dirty(bool). |
765 | 801 |
766 @param dirty dirty state | 802 @param dirty dirty state |
767 @type bool | 803 @type bool |
768 """ | 804 """ |
769 self.__dirty = dirty | 805 self.__dirty = dirty |
770 self.saveAct.setEnabled(dirty) | 806 self.saveAct.setEnabled(dirty) |
771 self.dirty.emit(dirty) | 807 self.dirty.emit(dirty) |
772 if self.__dirty: | 808 if self.__dirty: |
773 self.projectChanged.emit() | 809 self.projectChanged.emit() |
774 | 810 |
775 def isDirty(self): | 811 def isDirty(self): |
776 """ | 812 """ |
777 Public method to return the dirty state. | 813 Public method to return the dirty state. |
778 | 814 |
779 @return dirty state (boolean) | 815 @return dirty state (boolean) |
780 """ | 816 """ |
781 return self.__dirty | 817 return self.__dirty |
782 | 818 |
783 def isOpen(self): | 819 def isOpen(self): |
784 """ | 820 """ |
785 Public method to return the opened state. | 821 Public method to return the opened state. |
786 | 822 |
787 @return open state (boolean) | 823 @return open state (boolean) |
788 """ | 824 """ |
789 return self.opened | 825 return self.opened |
790 | 826 |
791 def __checkFilesExist(self, index): | 827 def __checkFilesExist(self, index): |
792 """ | 828 """ |
793 Private method to check, if the files in a list exist. | 829 Private method to check, if the files in a list exist. |
794 | 830 |
795 The files in the indicated list are checked for existance in the | 831 The files in the indicated list are checked for existance in the |
796 filesystem. Non existant files are removed from the list and the | 832 filesystem. Non existant files are removed from the list and the |
797 dirty state of the project is changed accordingly. | 833 dirty state of the project is changed accordingly. |
798 | 834 |
799 @param index key of the list to be checked (string) | 835 @param index key of the list to be checked (string) |
800 """ | 836 """ |
801 removed = False | 837 removed = False |
802 removelist = [] | 838 removelist = [] |
803 for file in self.pdata[index]: | 839 for file in self.pdata[index]: |
804 if not os.path.exists(os.path.join(self.ppath, file)): | 840 if not os.path.exists(os.path.join(self.ppath, file)): |
805 removelist.append(file) | 841 removelist.append(file) |
806 removed = True | 842 removed = True |
807 | 843 |
808 if removed: | 844 if removed: |
809 for file in removelist: | 845 for file in removelist: |
810 self.pdata[index].remove(file) | 846 self.pdata[index].remove(file) |
811 self.setDirty(True) | 847 self.setDirty(True) |
812 | 848 |
813 def __readProject(self, fn): | 849 def __readProject(self, fn): |
814 """ | 850 """ |
815 Private method to read in a project (.epj or .e4p) file. | 851 Private method to read in a project (.epj or .e4p) file. |
816 | 852 |
817 @param fn filename of the project file to be read (string) | 853 @param fn filename of the project file to be read (string) |
818 @return flag indicating success | 854 @return flag indicating success |
819 """ | 855 """ |
820 if os.path.splitext(fn)[1] == ".epj": | 856 if os.path.splitext(fn)[1] == ".epj": |
821 # new JSON based format | 857 # new JSON based format |
824 else: | 860 else: |
825 # old XML based format | 861 # old XML based format |
826 f = QFile(fn) | 862 f = QFile(fn) |
827 if f.open(QIODevice.OpenModeFlag.ReadOnly): | 863 if f.open(QIODevice.OpenModeFlag.ReadOnly): |
828 from EricXML.ProjectReader import ProjectReader | 864 from EricXML.ProjectReader import ProjectReader |
865 | |
829 reader = ProjectReader(f, self) | 866 reader = ProjectReader(f, self) |
830 reader.readXML() | 867 reader.readXML() |
831 res = not reader.hasError() | 868 res = not reader.hasError() |
832 f.close() | 869 f.close() |
833 | 870 |
834 # create hash value, if it doesn't have one | 871 # create hash value, if it doesn't have one |
835 if reader.version.startswith("5.") and not self.pdata["HASH"]: | 872 if reader.version.startswith("5.") and not self.pdata["HASH"]: |
836 hashStr = str(QCryptographicHash.hash( | 873 hashStr = str( |
837 QByteArray(self.ppath.encode("utf-8")), | 874 QCryptographicHash.hash( |
838 QCryptographicHash.Algorithm.Sha1).toHex(), | 875 QByteArray(self.ppath.encode("utf-8")), |
839 encoding="utf-8") | 876 QCryptographicHash.Algorithm.Sha1, |
877 ).toHex(), | |
878 encoding="utf-8", | |
879 ) | |
840 self.pdata["HASH"] = hashStr | 880 self.pdata["HASH"] = hashStr |
841 self.setDirty(True) | 881 self.setDirty(True) |
842 else: | 882 else: |
843 EricMessageBox.critical( | 883 EricMessageBox.critical( |
844 self.ui, | 884 self.ui, |
845 self.tr("Read Project File"), | 885 self.tr("Read Project File"), |
846 self.tr( | 886 self.tr( |
847 "<p>The project file <b>{0}</b> could not be read." | 887 "<p>The project file <b>{0}</b> could not be read." "</p>" |
848 "</p>") | 888 ).format(fn), |
849 .format(fn)) | 889 ) |
850 res = False | 890 res = False |
851 | 891 |
852 if res: | 892 if res: |
853 self.pfile = os.path.abspath(fn) | 893 self.pfile = os.path.abspath(fn) |
854 self.ppath = os.path.abspath(os.path.dirname(fn)) | 894 self.ppath = os.path.abspath(os.path.dirname(fn)) |
855 | 895 |
856 # insert filename into list of recently opened projects | 896 # insert filename into list of recently opened projects |
857 self.__syncRecent() | 897 self.__syncRecent() |
858 | 898 |
859 if self.pdata["TRANSLATIONPATTERN"]: | 899 if self.pdata["TRANSLATIONPATTERN"]: |
860 self.translationsRoot = self.pdata["TRANSLATIONPATTERN"].split( | 900 self.translationsRoot = self.pdata["TRANSLATIONPATTERN"].split( |
861 "%language%")[0] | 901 "%language%" |
902 )[0] | |
862 elif self.pdata["MAINSCRIPT"]: | 903 elif self.pdata["MAINSCRIPT"]: |
863 self.translationsRoot = os.path.splitext( | 904 self.translationsRoot = os.path.splitext(self.pdata["MAINSCRIPT"])[0] |
864 self.pdata["MAINSCRIPT"])[0] | |
865 if os.path.isdir(os.path.join(self.ppath, self.translationsRoot)): | 905 if os.path.isdir(os.path.join(self.ppath, self.translationsRoot)): |
866 dn = self.translationsRoot | 906 dn = self.translationsRoot |
867 else: | 907 else: |
868 dn = os.path.dirname(self.translationsRoot) | 908 dn = os.path.dirname(self.translationsRoot) |
869 if dn not in self.subdirs: | 909 if dn not in self.subdirs: |
870 self.subdirs.append(dn) | 910 self.subdirs.append(dn) |
871 | 911 |
872 self.name = os.path.splitext(os.path.basename(fn))[0] | 912 self.name = os.path.splitext(os.path.basename(fn))[0] |
873 | 913 |
874 # check, if the files of the project still exist in the | 914 # check, if the files of the project still exist in the |
875 # project directory | 915 # project directory |
876 self.__checkFilesExist("SOURCES") | 916 self.__checkFilesExist("SOURCES") |
877 self.__checkFilesExist("FORMS") | 917 self.__checkFilesExist("FORMS") |
878 self.__checkFilesExist("INTERFACES") | 918 self.__checkFilesExist("INTERFACES") |
879 self.__checkFilesExist("PROTOCOLS") | 919 self.__checkFilesExist("PROTOCOLS") |
880 self.__checkFilesExist("TRANSLATIONS") | 920 self.__checkFilesExist("TRANSLATIONS") |
881 self.__checkFilesExist("RESOURCES") | 921 self.__checkFilesExist("RESOURCES") |
882 self.__checkFilesExist("OTHERS") | 922 self.__checkFilesExist("OTHERS") |
883 | 923 |
884 # get the names of subdirectories the files are stored in | 924 # get the names of subdirectories the files are stored in |
885 for fn in ( | 925 for fn in ( |
886 self.pdata["SOURCES"] + | 926 self.pdata["SOURCES"] |
887 self.pdata["FORMS"] + | 927 + self.pdata["FORMS"] |
888 self.pdata["INTERFACES"] + | 928 + self.pdata["INTERFACES"] |
889 self.pdata["PROTOCOLS"] + | 929 + self.pdata["PROTOCOLS"] |
890 self.pdata["RESOURCES"] + | 930 + self.pdata["RESOURCES"] |
891 self.pdata["TRANSLATIONS"] | 931 + self.pdata["TRANSLATIONS"] |
892 ): | 932 ): |
893 dn = os.path.dirname(fn) | 933 dn = os.path.dirname(fn) |
894 if dn not in self.subdirs: | 934 if dn not in self.subdirs: |
895 self.subdirs.append(dn) | 935 self.subdirs.append(dn) |
896 | 936 |
897 # get the names of other subdirectories | 937 # get the names of other subdirectories |
898 for fn in self.pdata["OTHERS"]: | 938 for fn in self.pdata["OTHERS"]: |
899 dn = os.path.dirname(fn) | 939 dn = os.path.dirname(fn) |
900 if dn not in self.otherssubdirs: | 940 if dn not in self.otherssubdirs: |
901 self.otherssubdirs.append(dn) | 941 self.otherssubdirs.append(dn) |
902 | 942 |
903 return res | 943 return res |
904 | 944 |
905 def __writeProject(self, fn=None): | 945 def __writeProject(self, fn=None): |
906 """ | 946 """ |
907 Private method to save the project infos to a project file. | 947 Private method to save the project infos to a project file. |
908 | 948 |
909 @param fn optional filename of the project file to be written (string). | 949 @param fn optional filename of the project file to be written (string). |
910 If fn is None, the filename stored in the project object | 950 If fn is None, the filename stored in the project object |
911 is used. This is the 'save' action. If fn is given, this filename | 951 is used. This is the 'save' action. If fn is given, this filename |
912 is used instead of the one in the project object. This is the | 952 is used instead of the one in the project object. This is the |
913 'save as' action. | 953 'save as' action. |
914 @return flag indicating success | 954 @return flag indicating success |
915 """ | 955 """ |
916 if self.vcs is not None: | 956 if self.vcs is not None: |
917 self.pdata["VCSOPTIONS"] = copy.deepcopy(self.vcs.vcsGetOptions()) | 957 self.pdata["VCSOPTIONS"] = copy.deepcopy(self.vcs.vcsGetOptions()) |
918 self.pdata["VCSOTHERDATA"] = copy.deepcopy( | 958 self.pdata["VCSOTHERDATA"] = copy.deepcopy(self.vcs.vcsGetOtherData()) |
919 self.vcs.vcsGetOtherData()) | 959 |
920 | |
921 if not self.pdata["HASH"]: | 960 if not self.pdata["HASH"]: |
922 hashStr = str(QCryptographicHash.hash( | 961 hashStr = str( |
923 QByteArray(self.ppath.encode("utf-8")), | 962 QCryptographicHash.hash( |
924 QCryptographicHash.Algorithm.Sha1).toHex(), | 963 QByteArray(self.ppath.encode("utf-8")), |
925 encoding="utf-8") | 964 QCryptographicHash.Algorithm.Sha1, |
965 ).toHex(), | |
966 encoding="utf-8", | |
967 ) | |
926 self.pdata["HASH"] = hashStr | 968 self.pdata["HASH"] = hashStr |
927 | 969 |
928 if fn is None: | 970 if fn is None: |
929 fn = self.pfile | 971 fn = self.pfile |
930 | 972 |
931 with EricOverrideCursor(): | 973 with EricOverrideCursor(): |
932 res = self.__projectFile.writeFile(fn) | 974 res = self.__projectFile.writeFile(fn) |
933 | 975 |
934 if res: | 976 if res: |
935 self.pfile = os.path.abspath(fn) | 977 self.pfile = os.path.abspath(fn) |
936 self.ppath = os.path.abspath(os.path.dirname(fn)) | 978 self.ppath = os.path.abspath(os.path.dirname(fn)) |
937 self.name = os.path.splitext(os.path.basename(fn))[0] | 979 self.name = os.path.splitext(os.path.basename(fn))[0] |
938 self.setDirty(False) | 980 self.setDirty(False) |
939 | 981 |
940 # insert filename into list of recently opened projects | 982 # insert filename into list of recently opened projects |
941 self.__syncRecent() | 983 self.__syncRecent() |
942 | 984 |
943 return res | 985 return res |
944 | 986 |
945 def __readUserProperties(self): | 987 def __readUserProperties(self): |
946 """ | 988 """ |
947 Private method to read in the user specific project file (.eqj or | 989 Private method to read in the user specific project file (.eqj or |
948 .e4q). | 990 .e4q). |
949 """ | 991 """ |
950 if self.pfile is None: | 992 if self.pfile is None: |
951 return | 993 return |
952 | 994 |
953 fn1, ext = os.path.splitext(os.path.basename(self.pfile)) | 995 fn1, ext = os.path.splitext(os.path.basename(self.pfile)) |
954 fn = os.path.join(self.getProjectManagementDir(), | 996 fn = os.path.join(self.getProjectManagementDir(), "{0}.eqj".format(fn1)) |
955 '{0}.eqj'.format(fn1)) | |
956 if os.path.exists(fn): | 997 if os.path.exists(fn): |
957 # try the new JSON based format first | 998 # try the new JSON based format first |
958 self.__userProjectFile.readFile(fn) | 999 self.__userProjectFile.readFile(fn) |
959 else: | 1000 else: |
960 # try the old XML based format second | 1001 # try the old XML based format second |
961 fn = os.path.join(self.getProjectManagementDir(), | 1002 fn = os.path.join(self.getProjectManagementDir(), "{0}.e4q".format(fn1)) |
962 '{0}.e4q'.format(fn1)) | |
963 if os.path.exists(fn): | 1003 if os.path.exists(fn): |
964 f = QFile(fn) | 1004 f = QFile(fn) |
965 if f.open(QIODevice.OpenModeFlag.ReadOnly): | 1005 if f.open(QIODevice.OpenModeFlag.ReadOnly): |
966 from EricXML.UserProjectReader import UserProjectReader | 1006 from EricXML.UserProjectReader import UserProjectReader |
1007 | |
967 reader = UserProjectReader(f, self) | 1008 reader = UserProjectReader(f, self) |
968 reader.readXML() | 1009 reader.readXML() |
969 f.close() | 1010 f.close() |
970 else: | 1011 else: |
971 EricMessageBox.critical( | 1012 EricMessageBox.critical( |
972 self.ui, | 1013 self.ui, |
973 self.tr("Read User Project Properties"), | 1014 self.tr("Read User Project Properties"), |
974 self.tr( | 1015 self.tr( |
975 "<p>The user specific project properties file" | 1016 "<p>The user specific project properties file" |
976 " <b>{0}</b> could not be read.</p>").format(fn)) | 1017 " <b>{0}</b> could not be read.</p>" |
977 | 1018 ).format(fn), |
1019 ) | |
1020 | |
978 def __writeUserProperties(self): | 1021 def __writeUserProperties(self): |
979 """ | 1022 """ |
980 Private method to write the user specific project data to a JSON file. | 1023 Private method to write the user specific project data to a JSON file. |
981 """ | 1024 """ |
982 if self.pfile is None: | 1025 if self.pfile is None: |
983 return | 1026 return |
984 | 1027 |
985 fn, ext = os.path.splitext(os.path.basename(self.pfile)) | 1028 fn, ext = os.path.splitext(os.path.basename(self.pfile)) |
986 fn = os.path.join(self.getProjectManagementDir(), '{0}.eqj'.format(fn)) | 1029 fn = os.path.join(self.getProjectManagementDir(), "{0}.eqj".format(fn)) |
987 | 1030 |
988 with EricOverrideCursor(): | 1031 with EricOverrideCursor(): |
989 self.__userProjectFile.writeFile(fn) | 1032 self.__userProjectFile.writeFile(fn) |
990 | 1033 |
991 def __showContextMenuSession(self): | 1034 def __showContextMenuSession(self): |
992 """ | 1035 """ |
993 Private slot called before the Session menu is shown. | 1036 Private slot called before the Session menu is shown. |
994 """ | 1037 """ |
995 enable = True | 1038 enable = True |
996 if self.pfile is None: | 1039 if self.pfile is None: |
997 enable = False | 1040 enable = False |
998 else: | 1041 else: |
999 fn, ext = os.path.splitext(os.path.basename(self.pfile)) | 1042 fn, ext = os.path.splitext(os.path.basename(self.pfile)) |
1000 fn_new = os.path.join(self.getProjectManagementDir(), | 1043 fn_new = os.path.join(self.getProjectManagementDir(), "{0}.esj".format(fn)) |
1001 '{0}.esj'.format(fn)) | 1044 fn_old = os.path.join(self.getProjectManagementDir(), "{0}.e5s".format(fn)) |
1002 fn_old = os.path.join(self.getProjectManagementDir(), | |
1003 '{0}.e5s'.format(fn)) | |
1004 enable = os.path.exists(fn_new) or os.path.exists(fn_old) | 1045 enable = os.path.exists(fn_new) or os.path.exists(fn_old) |
1005 self.sessActGrp.findChild( | 1046 self.sessActGrp.findChild(QAction, "project_load_session").setEnabled(enable) |
1006 QAction, "project_load_session").setEnabled(enable) | 1047 self.sessActGrp.findChild(QAction, "project_delete_session").setEnabled(enable) |
1007 self.sessActGrp.findChild( | 1048 |
1008 QAction, "project_delete_session").setEnabled(enable) | |
1009 | |
1010 @pyqtSlot() | 1049 @pyqtSlot() |
1011 def __readSession(self, quiet=False, indicator=""): | 1050 def __readSession(self, quiet=False, indicator=""): |
1012 """ | 1051 """ |
1013 Private method to read in the project session file (.esj or .e5s). | 1052 Private method to read in the project session file (.esj or .e5s). |
1014 | 1053 |
1015 @param quiet flag indicating quiet operations. | 1054 @param quiet flag indicating quiet operations. |
1016 If this flag is true, no errors are reported. | 1055 If this flag is true, no errors are reported. |
1017 @param indicator indicator string (string) | 1056 @param indicator indicator string (string) |
1018 """ | 1057 """ |
1019 if self.pfile is None: | 1058 if self.pfile is None: |
1020 if not quiet: | 1059 if not quiet: |
1021 EricMessageBox.critical( | 1060 EricMessageBox.critical( |
1022 self.ui, | 1061 self.ui, |
1023 self.tr("Read Project Session"), | 1062 self.tr("Read Project Session"), |
1024 self.tr("Please save the project first.")) | 1063 self.tr("Please save the project first."), |
1064 ) | |
1025 return | 1065 return |
1026 | 1066 |
1027 fn1, ext = os.path.splitext(os.path.basename(self.pfile)) | 1067 fn1, ext = os.path.splitext(os.path.basename(self.pfile)) |
1028 fn = os.path.join(self.getProjectManagementDir(), | 1068 fn = os.path.join( |
1029 '{0}{1}.esj'.format(fn1, indicator)) | 1069 self.getProjectManagementDir(), "{0}{1}.esj".format(fn1, indicator) |
1070 ) | |
1030 if os.path.exists(fn): | 1071 if os.path.exists(fn): |
1031 # try the new JSON based format first | 1072 # try the new JSON based format first |
1032 self.__sessionFile.readFile(fn) | 1073 self.__sessionFile.readFile(fn) |
1033 else: | 1074 else: |
1034 # try the old XML based format second | 1075 # try the old XML based format second |
1035 fn = os.path.join(self.getProjectManagementDir(), | 1076 fn = os.path.join( |
1036 '{0}{1}.e5s'.format(fn1, indicator)) | 1077 self.getProjectManagementDir(), "{0}{1}.e5s".format(fn1, indicator) |
1078 ) | |
1037 if os.path.exists(fn): | 1079 if os.path.exists(fn): |
1038 f = QFile(fn) | 1080 f = QFile(fn) |
1039 if f.open(QIODevice.OpenModeFlag.ReadOnly): | 1081 if f.open(QIODevice.OpenModeFlag.ReadOnly): |
1040 from EricXML.SessionReader import SessionReader | 1082 from EricXML.SessionReader import SessionReader |
1083 | |
1041 reader = SessionReader(f, False) | 1084 reader = SessionReader(f, False) |
1042 reader.readXML(quiet=quiet) | 1085 reader.readXML(quiet=quiet) |
1043 f.close() | 1086 f.close() |
1044 else: | 1087 else: |
1045 if not quiet: | 1088 if not quiet: |
1046 EricMessageBox.critical( | 1089 EricMessageBox.critical( |
1047 self.ui, | 1090 self.ui, |
1048 self.tr("Read project session"), | 1091 self.tr("Read project session"), |
1049 self.tr( | 1092 self.tr( |
1050 "<p>The project session file <b>{0}</b> could" | 1093 "<p>The project session file <b>{0}</b> could" |
1051 " not be read.</p>").format(fn)) | 1094 " not be read.</p>" |
1052 | 1095 ).format(fn), |
1096 ) | |
1097 | |
1053 @pyqtSlot() | 1098 @pyqtSlot() |
1054 def __writeSession(self, quiet=False, indicator=""): | 1099 def __writeSession(self, quiet=False, indicator=""): |
1055 """ | 1100 """ |
1056 Private method to write the session data to an XML file (.esj). | 1101 Private method to write the session data to an XML file (.esj). |
1057 | 1102 |
1058 @param quiet flag indicating quiet operations. | 1103 @param quiet flag indicating quiet operations. |
1059 If this flag is true, no errors are reported. | 1104 If this flag is true, no errors are reported. |
1060 @param indicator indicator string (string) | 1105 @param indicator indicator string (string) |
1061 """ | 1106 """ |
1062 if self.pfile is None: | 1107 if self.pfile is None: |
1063 if not quiet: | 1108 if not quiet: |
1064 EricMessageBox.critical( | 1109 EricMessageBox.critical( |
1065 self.ui, | 1110 self.ui, |
1066 self.tr("Save Project Session"), | 1111 self.tr("Save Project Session"), |
1067 self.tr("Please save the project first.")) | 1112 self.tr("Please save the project first."), |
1113 ) | |
1068 return | 1114 return |
1069 | 1115 |
1070 fn, ext = os.path.splitext(os.path.basename(self.pfile)) | 1116 fn, ext = os.path.splitext(os.path.basename(self.pfile)) |
1071 fn = os.path.join(self.getProjectManagementDir(), | 1117 fn = os.path.join( |
1072 '{0}{1}.esj'.format(fn, indicator)) | 1118 self.getProjectManagementDir(), "{0}{1}.esj".format(fn, indicator) |
1073 | 1119 ) |
1120 | |
1074 self.__sessionFile.writeFile(fn) | 1121 self.__sessionFile.writeFile(fn) |
1075 | 1122 |
1076 def __deleteSession(self): | 1123 def __deleteSession(self): |
1077 """ | 1124 """ |
1078 Private method to delete the session file. | 1125 Private method to delete the session file. |
1079 """ | 1126 """ |
1080 if self.pfile is None: | 1127 if self.pfile is None: |
1081 EricMessageBox.critical( | 1128 EricMessageBox.critical( |
1082 self.ui, | 1129 self.ui, |
1083 self.tr("Delete Project Session"), | 1130 self.tr("Delete Project Session"), |
1084 self.tr("Please save the project first.")) | 1131 self.tr("Please save the project first."), |
1132 ) | |
1085 return | 1133 return |
1086 | 1134 |
1087 fname, ext = os.path.splitext(os.path.basename(self.pfile)) | 1135 fname, ext = os.path.splitext(os.path.basename(self.pfile)) |
1088 | 1136 |
1089 for ext in (".esj", ".e5s", ".e4s"): | 1137 for ext in (".esj", ".e5s", ".e4s"): |
1090 fn = os.path.join( | 1138 fn = os.path.join( |
1091 self.getProjectManagementDir(), "{0}{1}".format(fname, ext)) | 1139 self.getProjectManagementDir(), "{0}{1}".format(fname, ext) |
1140 ) | |
1092 if os.path.exists(fn): | 1141 if os.path.exists(fn): |
1093 try: | 1142 try: |
1094 os.remove(fn) | 1143 os.remove(fn) |
1095 except OSError: | 1144 except OSError: |
1096 EricMessageBox.critical( | 1145 EricMessageBox.critical( |
1097 self.ui, | 1146 self.ui, |
1098 self.tr("Delete Project Session"), | 1147 self.tr("Delete Project Session"), |
1099 self.tr( | 1148 self.tr( |
1100 "<p>The project session file <b>{0}</b> could" | 1149 "<p>The project session file <b>{0}</b> could" |
1101 " not be deleted.</p>").format(fn)) | 1150 " not be deleted.</p>" |
1102 | 1151 ).format(fn), |
1152 ) | |
1153 | |
1103 def __readTasks(self): | 1154 def __readTasks(self): |
1104 """ | 1155 """ |
1105 Private method to read in the project tasks file (.etj or .e6t). | 1156 Private method to read in the project tasks file (.etj or .e6t). |
1106 """ | 1157 """ |
1107 if self.pfile is None: | 1158 if self.pfile is None: |
1108 EricMessageBox.critical( | 1159 EricMessageBox.critical( |
1109 self.ui, | 1160 self.ui, |
1110 self.tr("Read Tasks"), | 1161 self.tr("Read Tasks"), |
1111 self.tr("Please save the project first.")) | 1162 self.tr("Please save the project first."), |
1163 ) | |
1112 return | 1164 return |
1113 | 1165 |
1114 base, ext = os.path.splitext(os.path.basename(self.pfile)) | 1166 base, ext = os.path.splitext(os.path.basename(self.pfile)) |
1115 fn = os.path.join(self.getProjectManagementDir(), | 1167 fn = os.path.join(self.getProjectManagementDir(), "{0}.etj".format(base)) |
1116 '{0}.etj'.format(base)) | |
1117 if os.path.exists(fn): | 1168 if os.path.exists(fn): |
1118 # try new style JSON file first | 1169 # try new style JSON file first |
1119 self.__tasksFile.readFile(fn) | 1170 self.__tasksFile.readFile(fn) |
1120 else: | 1171 else: |
1121 # try old style XML file second | 1172 # try old style XML file second |
1122 fn = os.path.join(self.getProjectManagementDir(), | 1173 fn = os.path.join(self.getProjectManagementDir(), "{0}.e6t".format(base)) |
1123 '{0}.e6t'.format(base)) | |
1124 if os.path.exists(fn): | 1174 if os.path.exists(fn): |
1125 f = QFile(fn) | 1175 f = QFile(fn) |
1126 if f.open(QIODevice.OpenModeFlag.ReadOnly): | 1176 if f.open(QIODevice.OpenModeFlag.ReadOnly): |
1127 from EricXML.TasksReader import TasksReader | 1177 from EricXML.TasksReader import TasksReader |
1178 | |
1128 reader = TasksReader(f, True) | 1179 reader = TasksReader(f, True) |
1129 reader.readXML() | 1180 reader.readXML() |
1130 f.close() | 1181 f.close() |
1131 else: | 1182 else: |
1132 EricMessageBox.critical( | 1183 EricMessageBox.critical( |
1133 self.ui, | 1184 self.ui, |
1134 self.tr("Read Tasks"), | 1185 self.tr("Read Tasks"), |
1135 self.tr( | 1186 self.tr( |
1136 "<p>The tasks file <b>{0}</b> could not be read." | 1187 "<p>The tasks file <b>{0}</b> could not be read." "</p>" |
1137 "</p>") | 1188 ).format(fn), |
1138 .format(fn)) | 1189 ) |
1139 | 1190 |
1140 def writeTasks(self): | 1191 def writeTasks(self): |
1141 """ | 1192 """ |
1142 Public method to write the tasks data to a JSON file (.etj). | 1193 Public method to write the tasks data to a JSON file (.etj). |
1143 """ | 1194 """ |
1144 if self.pfile is None: | 1195 if self.pfile is None: |
1145 return | 1196 return |
1146 | 1197 |
1147 fn, ext = os.path.splitext(os.path.basename(self.pfile)) | 1198 fn, ext = os.path.splitext(os.path.basename(self.pfile)) |
1148 | 1199 |
1149 fn = os.path.join(self.getProjectManagementDir(), | 1200 fn = os.path.join(self.getProjectManagementDir(), "{0}.etj".format(fn)) |
1150 '{0}.etj'.format(fn)) | |
1151 self.__tasksFile.writeFile(fn) | 1201 self.__tasksFile.writeFile(fn) |
1152 | 1202 |
1153 def __showContextMenuDebugger(self): | 1203 def __showContextMenuDebugger(self): |
1154 """ | 1204 """ |
1155 Private slot called before the Debugger menu is shown. | 1205 Private slot called before the Debugger menu is shown. |
1156 """ | 1206 """ |
1157 enable = True | 1207 enable = True |
1158 if self.pfile is None: | 1208 if self.pfile is None: |
1159 enable = False | 1209 enable = False |
1160 else: | 1210 else: |
1161 fn, ext = os.path.splitext(os.path.basename(self.pfile)) | 1211 fn, ext = os.path.splitext(os.path.basename(self.pfile)) |
1162 # try new style file first | 1212 # try new style file first |
1163 fn = os.path.join(self.getProjectManagementDir(), | 1213 fn = os.path.join(self.getProjectManagementDir(), "{0}.edj".format(fn)) |
1164 '{0}.edj'.format(fn)) | |
1165 if not os.path.exists(fn): | 1214 if not os.path.exists(fn): |
1166 # try old style file second | 1215 # try old style file second |
1167 fn = os.path.join(self.getProjectManagementDir(), | 1216 fn = os.path.join(self.getProjectManagementDir(), "{0}.e4d".format(fn)) |
1168 '{0}.e4d'.format(fn)) | |
1169 enable = os.path.exists(fn) | 1217 enable = os.path.exists(fn) |
1170 self.dbgActGrp.findChild( | 1218 self.dbgActGrp.findChild( |
1171 QAction, "project_debugger_properties_load").setEnabled(enable) | 1219 QAction, "project_debugger_properties_load" |
1220 ).setEnabled(enable) | |
1172 self.dbgActGrp.findChild( | 1221 self.dbgActGrp.findChild( |
1173 QAction, "project_debugger_properties_delete").setEnabled(enable) | 1222 QAction, "project_debugger_properties_delete" |
1174 | 1223 ).setEnabled(enable) |
1224 | |
1175 @pyqtSlot() | 1225 @pyqtSlot() |
1176 def __readDebugProperties(self, quiet=False): | 1226 def __readDebugProperties(self, quiet=False): |
1177 """ | 1227 """ |
1178 Private method to read in the project debugger properties file | 1228 Private method to read in the project debugger properties file |
1179 (.edj or .e4d). | 1229 (.edj or .e4d). |
1180 | 1230 |
1181 @param quiet flag indicating quiet operations. | 1231 @param quiet flag indicating quiet operations. |
1182 If this flag is true, no errors are reported. | 1232 If this flag is true, no errors are reported. |
1183 """ | 1233 """ |
1184 if self.pfile is None: | 1234 if self.pfile is None: |
1185 if not quiet: | 1235 if not quiet: |
1186 EricMessageBox.critical( | 1236 EricMessageBox.critical( |
1187 self.ui, | 1237 self.ui, |
1188 self.tr("Read Debugger Properties"), | 1238 self.tr("Read Debugger Properties"), |
1189 self.tr("Please save the project first.")) | 1239 self.tr("Please save the project first."), |
1240 ) | |
1190 return | 1241 return |
1191 | 1242 |
1192 fn1, ext = os.path.splitext(os.path.basename(self.pfile)) | 1243 fn1, ext = os.path.splitext(os.path.basename(self.pfile)) |
1193 fn = os.path.join(self.getProjectManagementDir(), | 1244 fn = os.path.join(self.getProjectManagementDir(), "{0}.edj".format(fn1)) |
1194 '{0}.edj'.format(fn1)) | |
1195 if os.path.exists(fn): | 1245 if os.path.exists(fn): |
1196 # try the new JSON based format first | 1246 # try the new JSON based format first |
1197 if self.__debuggerPropertiesFile.readFile(fn): | 1247 if self.__debuggerPropertiesFile.readFile(fn): |
1198 self.debugPropertiesLoaded = True | 1248 self.debugPropertiesLoaded = True |
1199 self.debugPropertiesChanged = False | 1249 self.debugPropertiesChanged = False |
1200 else: | 1250 else: |
1201 # try the old XML based format second | 1251 # try the old XML based format second |
1202 fn = os.path.join(self.getProjectManagementDir(), | 1252 fn = os.path.join(self.getProjectManagementDir(), "{0}.e4d".format(fn1)) |
1203 '{0}.e4d'.format(fn1)) | 1253 |
1204 | |
1205 f = QFile(fn) | 1254 f = QFile(fn) |
1206 if f.open(QIODevice.OpenModeFlag.ReadOnly): | 1255 if f.open(QIODevice.OpenModeFlag.ReadOnly): |
1207 from EricXML.DebuggerPropertiesReader import ( | 1256 from EricXML.DebuggerPropertiesReader import DebuggerPropertiesReader |
1208 DebuggerPropertiesReader | 1257 |
1209 ) | |
1210 reader = DebuggerPropertiesReader(f, self) | 1258 reader = DebuggerPropertiesReader(f, self) |
1211 reader.readXML(quiet=quiet) | 1259 reader.readXML(quiet=quiet) |
1212 f.close() | 1260 f.close() |
1213 self.debugPropertiesLoaded = True | 1261 self.debugPropertiesLoaded = True |
1214 self.debugPropertiesChanged = False | 1262 self.debugPropertiesChanged = False |
1217 EricMessageBox.critical( | 1265 EricMessageBox.critical( |
1218 self.ui, | 1266 self.ui, |
1219 self.tr("Read Debugger Properties"), | 1267 self.tr("Read Debugger Properties"), |
1220 self.tr( | 1268 self.tr( |
1221 "<p>The project debugger properties file" | 1269 "<p>The project debugger properties file" |
1222 " <b>{0}</b> could not be read.</p>").format(fn)) | 1270 " <b>{0}</b> could not be read.</p>" |
1223 | 1271 ).format(fn), |
1272 ) | |
1273 | |
1224 @pyqtSlot() | 1274 @pyqtSlot() |
1225 def __writeDebugProperties(self, quiet=False): | 1275 def __writeDebugProperties(self, quiet=False): |
1226 """ | 1276 """ |
1227 Private method to write the project debugger properties file (.edj). | 1277 Private method to write the project debugger properties file (.edj). |
1228 | 1278 |
1229 @param quiet flag indicating quiet operations. | 1279 @param quiet flag indicating quiet operations. |
1230 If this flag is true, no errors are reported. | 1280 If this flag is true, no errors are reported. |
1231 """ | 1281 """ |
1232 if self.pfile is None: | 1282 if self.pfile is None: |
1233 if not quiet: | 1283 if not quiet: |
1234 EricMessageBox.critical( | 1284 EricMessageBox.critical( |
1235 self.ui, | 1285 self.ui, |
1236 self.tr("Save Debugger Properties"), | 1286 self.tr("Save Debugger Properties"), |
1237 self.tr("Please save the project first.")) | 1287 self.tr("Please save the project first."), |
1288 ) | |
1238 return | 1289 return |
1239 | 1290 |
1240 fn, ext = os.path.splitext(os.path.basename(self.pfile)) | 1291 fn, ext = os.path.splitext(os.path.basename(self.pfile)) |
1241 fn = os.path.join(self.getProjectManagementDir(), '{0}.edj'.format(fn)) | 1292 fn = os.path.join(self.getProjectManagementDir(), "{0}.edj".format(fn)) |
1242 | 1293 |
1243 with EricOverrideCursor(): | 1294 with EricOverrideCursor(): |
1244 self.__debuggerPropertiesFile.writeFile(fn) | 1295 self.__debuggerPropertiesFile.writeFile(fn) |
1245 | 1296 |
1246 def __deleteDebugProperties(self): | 1297 def __deleteDebugProperties(self): |
1247 """ | 1298 """ |
1248 Private method to delete the project debugger properties file | 1299 Private method to delete the project debugger properties file |
1249 (.edj or .e4d). | 1300 (.edj or .e4d). |
1250 """ | 1301 """ |
1251 if self.pfile is None: | 1302 if self.pfile is None: |
1252 EricMessageBox.critical( | 1303 EricMessageBox.critical( |
1253 self.ui, | 1304 self.ui, |
1254 self.tr("Delete Debugger Properties"), | 1305 self.tr("Delete Debugger Properties"), |
1255 self.tr("Please save the project first.")) | 1306 self.tr("Please save the project first."), |
1307 ) | |
1256 return | 1308 return |
1257 | 1309 |
1258 fname, ext = os.path.splitext(os.path.basename(self.pfile)) | 1310 fname, ext = os.path.splitext(os.path.basename(self.pfile)) |
1259 | 1311 |
1260 for ext in (".edj", ".e4d"): | 1312 for ext in (".edj", ".e4d"): |
1261 fn = os.path.join(self.getProjectManagementDir(), | 1313 fn = os.path.join( |
1262 "{0}{1}".format(fname, ext)) | 1314 self.getProjectManagementDir(), "{0}{1}".format(fname, ext) |
1315 ) | |
1263 if os.path.exists(fn): | 1316 if os.path.exists(fn): |
1264 try: | 1317 try: |
1265 os.remove(fn) | 1318 os.remove(fn) |
1266 except OSError: | 1319 except OSError: |
1267 EricMessageBox.critical( | 1320 EricMessageBox.critical( |
1268 self.ui, | 1321 self.ui, |
1269 self.tr("Delete Debugger Properties"), | 1322 self.tr("Delete Debugger Properties"), |
1270 self.tr( | 1323 self.tr( |
1271 "<p>The project debugger properties file" | 1324 "<p>The project debugger properties file" |
1272 " <b>{0}</b> could not be deleted.</p>") | 1325 " <b>{0}</b> could not be deleted.</p>" |
1273 .format(fn)) | 1326 ).format(fn), |
1274 | 1327 ) |
1328 | |
1275 def __initDebugProperties(self): | 1329 def __initDebugProperties(self): |
1276 """ | 1330 """ |
1277 Private method to initialize the debug properties. | 1331 Private method to initialize the debug properties. |
1278 """ | 1332 """ |
1279 self.debugPropertiesLoaded = False | 1333 self.debugPropertiesLoaded = False |
1292 "CONSOLEDEBUGGER": False, | 1346 "CONSOLEDEBUGGER": False, |
1293 "CONSOLECOMMAND": "", | 1347 "CONSOLECOMMAND": "", |
1294 "REDIRECT": False, | 1348 "REDIRECT": False, |
1295 "NOENCODING": False, | 1349 "NOENCODING": False, |
1296 } | 1350 } |
1297 | 1351 |
1298 def isDebugPropertiesLoaded(self): | 1352 def isDebugPropertiesLoaded(self): |
1299 """ | 1353 """ |
1300 Public method to return the status of the debug properties. | 1354 Public method to return the status of the debug properties. |
1301 | 1355 |
1302 @return load status of debug properties (boolean) | 1356 @return load status of debug properties (boolean) |
1303 """ | 1357 """ |
1304 return self.debugPropertiesLoaded | 1358 return self.debugPropertiesLoaded |
1305 | 1359 |
1306 def __showDebugProperties(self): | 1360 def __showDebugProperties(self): |
1307 """ | 1361 """ |
1308 Private slot to display the debugger properties dialog. | 1362 Private slot to display the debugger properties dialog. |
1309 """ | 1363 """ |
1310 from .DebuggerPropertiesDialog import DebuggerPropertiesDialog | 1364 from .DebuggerPropertiesDialog import DebuggerPropertiesDialog |
1365 | |
1311 dlg = DebuggerPropertiesDialog(self) | 1366 dlg = DebuggerPropertiesDialog(self) |
1312 if dlg.exec() == QDialog.DialogCode.Accepted: | 1367 if dlg.exec() == QDialog.DialogCode.Accepted: |
1313 dlg.storeData() | 1368 dlg.storeData() |
1314 | 1369 |
1315 def getDebugProperty(self, key): | 1370 def getDebugProperty(self, key): |
1316 """ | 1371 """ |
1317 Public method to retrieve a debugger property. | 1372 Public method to retrieve a debugger property. |
1318 | 1373 |
1319 @param key key of the property (string) | 1374 @param key key of the property (string) |
1320 @return value of the property | 1375 @return value of the property |
1321 """ | 1376 """ |
1322 if key == "INTERPRETER": | 1377 if key == "INTERPRETER": |
1323 return ( | 1378 return ( |
1324 ericApp().getObject("VirtualEnvManager") | 1379 ericApp() |
1380 .getObject("VirtualEnvManager") | |
1325 .getVirtualenvInterpreter(self.debugProperties["VIRTUALENV"]) | 1381 .getVirtualenvInterpreter(self.debugProperties["VIRTUALENV"]) |
1326 ) | 1382 ) |
1327 else: | 1383 else: |
1328 return self.debugProperties[key] | 1384 return self.debugProperties[key] |
1329 | 1385 |
1330 def setDbgInfo(self, venvName, argv, wd, env, excReporting, excList, | 1386 def setDbgInfo( |
1331 excIgnoreList, autoClearShell, tracePython=None, | 1387 self, |
1332 autoContinue=None, enableMultiprocess=None, | 1388 venvName, |
1333 multiprocessNoDebug=None, configOverride=None): | 1389 argv, |
1390 wd, | |
1391 env, | |
1392 excReporting, | |
1393 excList, | |
1394 excIgnoreList, | |
1395 autoClearShell, | |
1396 tracePython=None, | |
1397 autoContinue=None, | |
1398 enableMultiprocess=None, | |
1399 multiprocessNoDebug=None, | |
1400 configOverride=None, | |
1401 ): | |
1334 """ | 1402 """ |
1335 Public method to set the debugging information. | 1403 Public method to set the debugging information. |
1336 | 1404 |
1337 @param venvName name of the virtual environment used | 1405 @param venvName name of the virtual environment used |
1338 @type str | 1406 @type str |
1339 @param argv command line arguments to be used | 1407 @param argv command line arguments to be used |
1340 @type str | 1408 @type str |
1341 @param wd working directory | 1409 @param wd working directory |
1370 self.dbgVirtualEnv = venvName | 1438 self.dbgVirtualEnv = venvName |
1371 self.dbgCmdline = argv | 1439 self.dbgCmdline = argv |
1372 self.dbgWd = wd | 1440 self.dbgWd = wd |
1373 self.dbgEnv = env | 1441 self.dbgEnv = env |
1374 self.dbgReportExceptions = excReporting | 1442 self.dbgReportExceptions = excReporting |
1375 self.dbgExcList = excList[:] # keep a copy of the list | 1443 self.dbgExcList = excList[:] # keep a copy of the list |
1376 self.dbgExcIgnoreList = excIgnoreList[:] # keep a copy of the list | 1444 self.dbgExcIgnoreList = excIgnoreList[:] # keep a copy of the list |
1377 self.dbgAutoClearShell = autoClearShell | 1445 self.dbgAutoClearShell = autoClearShell |
1378 if tracePython is not None: | 1446 if tracePython is not None: |
1379 self.dbgTracePython = tracePython | 1447 self.dbgTracePython = tracePython |
1380 if autoContinue is not None: | 1448 if autoContinue is not None: |
1381 self.dbgAutoContinue = autoContinue | 1449 self.dbgAutoContinue = autoContinue |
1383 self.dbgEnableMultiprocess = enableMultiprocess | 1451 self.dbgEnableMultiprocess = enableMultiprocess |
1384 if multiprocessNoDebug is not None: | 1452 if multiprocessNoDebug is not None: |
1385 self.dbgMultiprocessNoDebug = multiprocessNoDebug | 1453 self.dbgMultiprocessNoDebug = multiprocessNoDebug |
1386 if configOverride is not None: | 1454 if configOverride is not None: |
1387 self.dbgGlobalConfigOverride = copy.deepcopy(configOverride) | 1455 self.dbgGlobalConfigOverride = copy.deepcopy(configOverride) |
1388 | 1456 |
1389 def getTranslationPattern(self): | 1457 def getTranslationPattern(self): |
1390 """ | 1458 """ |
1391 Public method to get the translation pattern. | 1459 Public method to get the translation pattern. |
1392 | 1460 |
1393 @return translation pattern (string) | 1461 @return translation pattern (string) |
1394 """ | 1462 """ |
1395 return self.pdata["TRANSLATIONPATTERN"] | 1463 return self.pdata["TRANSLATIONPATTERN"] |
1396 | 1464 |
1397 def setTranslationPattern(self, pattern): | 1465 def setTranslationPattern(self, pattern): |
1398 """ | 1466 """ |
1399 Public method to set the translation pattern. | 1467 Public method to set the translation pattern. |
1400 | 1468 |
1401 @param pattern translation pattern | 1469 @param pattern translation pattern |
1402 @type str | 1470 @type str |
1403 """ | 1471 """ |
1404 self.pdata["TRANSLATIONPATTERN"] = pattern | 1472 self.pdata["TRANSLATIONPATTERN"] = pattern |
1405 | 1473 |
1406 def addLanguage(self): | 1474 def addLanguage(self): |
1407 """ | 1475 """ |
1408 Public slot used to add a language to the project. | 1476 Public slot used to add a language to the project. |
1409 """ | 1477 """ |
1410 if not self.pdata["TRANSLATIONPATTERN"]: | 1478 if not self.pdata["TRANSLATIONPATTERN"]: |
1411 EricMessageBox.critical( | 1479 EricMessageBox.critical( |
1412 self.ui, | 1480 self.ui, |
1413 self.tr("Add Language"), | 1481 self.tr("Add Language"), |
1414 self.tr( | 1482 self.tr("You have to specify a translation pattern first."), |
1415 "You have to specify a translation pattern first.")) | 1483 ) |
1416 return | 1484 return |
1417 | 1485 |
1418 from .AddLanguageDialog import AddLanguageDialog | 1486 from .AddLanguageDialog import AddLanguageDialog |
1487 | |
1419 dlg = AddLanguageDialog(self.parent()) | 1488 dlg = AddLanguageDialog(self.parent()) |
1420 if dlg.exec() == QDialog.DialogCode.Accepted: | 1489 if dlg.exec() == QDialog.DialogCode.Accepted: |
1421 lang = dlg.getSelectedLanguage() | 1490 lang = dlg.getSelectedLanguage() |
1422 if self.pdata["PROJECTTYPE"] in [ | 1491 if self.pdata["PROJECTTYPE"] in [ |
1423 "PyQt5", "PyQt5C", "PyQt6", "PyQt6C", "E7Plugin", | 1492 "PyQt5", |
1424 "PySide2", "PySide2C", "PySide6", "PySide6C" | 1493 "PyQt5C", |
1494 "PyQt6", | |
1495 "PyQt6C", | |
1496 "E7Plugin", | |
1497 "PySide2", | |
1498 "PySide2C", | |
1499 "PySide6", | |
1500 "PySide6C", | |
1425 ]: | 1501 ]: |
1426 langFile = self.pdata["TRANSLATIONPATTERN"].replace( | 1502 langFile = self.pdata["TRANSLATIONPATTERN"].replace("%language%", lang) |
1427 "%language%", lang) | |
1428 self.appendFile(langFile) | 1503 self.appendFile(langFile) |
1429 self.projectLanguageAddedByCode.emit(lang) | 1504 self.projectLanguageAddedByCode.emit(lang) |
1430 | 1505 |
1431 def __binaryTranslationFile(self, langFile): | 1506 def __binaryTranslationFile(self, langFile): |
1432 """ | 1507 """ |
1433 Private method to calculate the filename of the binary translations | 1508 Private method to calculate the filename of the binary translations |
1434 file given the name of the raw translations file. | 1509 file given the name of the raw translations file. |
1435 | 1510 |
1436 @param langFile name of the raw translations file (string) | 1511 @param langFile name of the raw translations file (string) |
1437 @return name of the binary translations file (string) | 1512 @return name of the binary translations file (string) |
1438 """ | 1513 """ |
1439 qmFile = "" | 1514 qmFile = "" |
1440 try: | 1515 try: |
1441 if self.__binaryTranslationsCallbacks[ | 1516 if ( |
1442 self.pdata["PROJECTTYPE"]] is not None: | 1517 self.__binaryTranslationsCallbacks[self.pdata["PROJECTTYPE"]] |
1443 qmFile = self.__binaryTranslationsCallbacks[ | 1518 is not None |
1444 self.pdata["PROJECTTYPE"]](langFile) | 1519 ): |
1520 qmFile = self.__binaryTranslationsCallbacks[self.pdata["PROJECTTYPE"]]( | |
1521 langFile | |
1522 ) | |
1445 except KeyError: | 1523 except KeyError: |
1446 qmFile = langFile.replace('.ts', '.qm') | 1524 qmFile = langFile.replace(".ts", ".qm") |
1447 if qmFile == langFile: | 1525 if qmFile == langFile: |
1448 qmFile = "" | 1526 qmFile = "" |
1449 return qmFile | 1527 return qmFile |
1450 | 1528 |
1451 def checkLanguageFiles(self): | 1529 def checkLanguageFiles(self): |
1452 """ | 1530 """ |
1453 Public slot to check the language files after a release process. | 1531 Public slot to check the language files after a release process. |
1454 """ | 1532 """ |
1455 tbPath = self.pdata["TRANSLATIONSBINPATH"] | 1533 tbPath = self.pdata["TRANSLATIONSBINPATH"] |
1456 for langFile in self.pdata["TRANSLATIONS"][:]: | 1534 for langFile in self.pdata["TRANSLATIONS"][:]: |
1457 qmFile = self.__binaryTranslationFile(langFile) | 1535 qmFile = self.__binaryTranslationFile(langFile) |
1458 if qmFile: | 1536 if qmFile: |
1459 if ( | 1537 if qmFile not in self.pdata["TRANSLATIONS"] and os.path.exists( |
1460 qmFile not in self.pdata["TRANSLATIONS"] and | 1538 os.path.join(self.ppath, qmFile) |
1461 os.path.exists(os.path.join(self.ppath, qmFile)) | |
1462 ): | 1539 ): |
1463 self.appendFile(qmFile) | 1540 self.appendFile(qmFile) |
1464 if tbPath: | 1541 if tbPath: |
1465 qmFile = os.path.join(tbPath, os.path.basename(qmFile)) | 1542 qmFile = os.path.join(tbPath, os.path.basename(qmFile)) |
1466 if ( | 1543 if qmFile not in self.pdata["TRANSLATIONS"] and os.path.exists( |
1467 qmFile not in self.pdata["TRANSLATIONS"] and | 1544 os.path.join(self.ppath, qmFile) |
1468 os.path.exists(os.path.join(self.ppath, qmFile)) | |
1469 ): | 1545 ): |
1470 self.appendFile(qmFile) | 1546 self.appendFile(qmFile) |
1471 | 1547 |
1472 def removeLanguageFile(self, langFile): | 1548 def removeLanguageFile(self, langFile): |
1473 """ | 1549 """ |
1474 Public slot to remove a translation from the project. | 1550 Public slot to remove a translation from the project. |
1475 | 1551 |
1476 The translation file is not deleted from the project directory. | 1552 The translation file is not deleted from the project directory. |
1477 | 1553 |
1478 @param langFile the translation file to be removed (string) | 1554 @param langFile the translation file to be removed (string) |
1479 """ | 1555 """ |
1480 langFile = self.getRelativePath(langFile) | 1556 langFile = self.getRelativePath(langFile) |
1481 qmFile = self.__binaryTranslationFile(langFile) | 1557 qmFile = self.__binaryTranslationFile(langFile) |
1482 self.pdata["TRANSLATIONS"].remove(langFile) | 1558 self.pdata["TRANSLATIONS"].remove(langFile) |
1483 self.__model.removeItem(langFile) | 1559 self.__model.removeItem(langFile) |
1484 if qmFile: | 1560 if qmFile: |
1485 with contextlib.suppress(ValueError): | 1561 with contextlib.suppress(ValueError): |
1486 if self.pdata["TRANSLATIONSBINPATH"]: | 1562 if self.pdata["TRANSLATIONSBINPATH"]: |
1487 qmFile = self.getRelativePath( | 1563 qmFile = self.getRelativePath( |
1488 os.path.join(self.pdata["TRANSLATIONSBINPATH"], | 1564 os.path.join( |
1489 os.path.basename(qmFile))) | 1565 self.pdata["TRANSLATIONSBINPATH"], os.path.basename(qmFile) |
1566 ) | |
1567 ) | |
1490 self.pdata["TRANSLATIONS"].remove(qmFile) | 1568 self.pdata["TRANSLATIONS"].remove(qmFile) |
1491 self.__model.removeItem(qmFile) | 1569 self.__model.removeItem(qmFile) |
1492 self.setDirty(True) | 1570 self.setDirty(True) |
1493 | 1571 |
1494 def deleteLanguageFile(self, langFile): | 1572 def deleteLanguageFile(self, langFile): |
1495 """ | 1573 """ |
1496 Public slot to delete a translation from the project directory. | 1574 Public slot to delete a translation from the project directory. |
1497 | 1575 |
1498 @param langFile the translation file to be removed (string) | 1576 @param langFile the translation file to be removed (string) |
1499 """ | 1577 """ |
1500 try: | 1578 try: |
1501 from send2trash import send2trash as s2t | 1579 from send2trash import send2trash as s2t |
1502 except ImportError: | 1580 except ImportError: |
1503 s2t = os.remove | 1581 s2t = os.remove |
1504 | 1582 |
1505 langFile = self.getRelativePath(langFile) | 1583 langFile = self.getRelativePath(langFile) |
1506 qmFile = self.__binaryTranslationFile(langFile) | 1584 qmFile = self.__binaryTranslationFile(langFile) |
1507 | 1585 |
1508 try: | 1586 try: |
1509 fn = os.path.join(self.ppath, langFile) | 1587 fn = os.path.join(self.ppath, langFile) |
1510 if os.path.exists(fn): | 1588 if os.path.exists(fn): |
1511 s2t(fn) | 1589 s2t(fn) |
1512 except OSError as err: | 1590 except OSError as err: |
1513 EricMessageBox.critical( | 1591 EricMessageBox.critical( |
1514 self.ui, | 1592 self.ui, |
1515 self.tr("Delete translation"), | 1593 self.tr("Delete translation"), |
1516 self.tr( | 1594 self.tr( |
1517 "<p>The selected translation file <b>{0}</b> could not be" | 1595 "<p>The selected translation file <b>{0}</b> could not be" |
1518 " deleted.</p><p>Reason: {1}</p>").format( | 1596 " deleted.</p><p>Reason: {1}</p>" |
1519 langFile, str(err))) | 1597 ).format(langFile, str(err)), |
1598 ) | |
1520 return | 1599 return |
1521 | 1600 |
1522 self.removeLanguageFile(langFile) | 1601 self.removeLanguageFile(langFile) |
1523 | 1602 |
1524 # now get rid of the .qm file | 1603 # now get rid of the .qm file |
1525 if qmFile: | 1604 if qmFile: |
1526 try: | 1605 try: |
1527 if self.pdata["TRANSLATIONSBINPATH"]: | 1606 if self.pdata["TRANSLATIONSBINPATH"]: |
1528 qmFile = self.getRelativePath( | 1607 qmFile = self.getRelativePath( |
1529 os.path.join(self.pdata["TRANSLATIONSBINPATH"], | 1608 os.path.join( |
1530 os.path.basename(qmFile))) | 1609 self.pdata["TRANSLATIONSBINPATH"], os.path.basename(qmFile) |
1610 ) | |
1611 ) | |
1531 fn = os.path.join(self.ppath, qmFile) | 1612 fn = os.path.join(self.ppath, qmFile) |
1532 if os.path.exists(fn): | 1613 if os.path.exists(fn): |
1533 s2t(fn) | 1614 s2t(fn) |
1534 except OSError as err: | 1615 except OSError as err: |
1535 EricMessageBox.critical( | 1616 EricMessageBox.critical( |
1536 self.ui, | 1617 self.ui, |
1537 self.tr("Delete translation"), | 1618 self.tr("Delete translation"), |
1538 self.tr( | 1619 self.tr( |
1539 "<p>The selected translation file <b>{0}</b> could" | 1620 "<p>The selected translation file <b>{0}</b> could" |
1540 " not be deleted.</p><p>Reason: {1}</p>").format( | 1621 " not be deleted.</p><p>Reason: {1}</p>" |
1541 qmFile, str(err))) | 1622 ).format(qmFile, str(err)), |
1623 ) | |
1542 return | 1624 return |
1543 | 1625 |
1544 def appendFile(self, fn, isSourceFile=False, updateModel=True): | 1626 def appendFile(self, fn, isSourceFile=False, updateModel=True): |
1545 """ | 1627 """ |
1546 Public method to append a file to the project. | 1628 Public method to append a file to the project. |
1547 | 1629 |
1548 @param fn filename to be added to the project (string) | 1630 @param fn filename to be added to the project (string) |
1549 @param isSourceFile flag indicating that this is a source file | 1631 @param isSourceFile flag indicating that this is a source file |
1550 even if it doesn't have the source extension (boolean) | 1632 even if it doesn't have the source extension (boolean) |
1551 @param updateModel flag indicating an update of the model is | 1633 @param updateModel flag indicating an update of the model is |
1552 requested (boolean) | 1634 requested (boolean) |
1553 """ | 1635 """ |
1554 dirty = False | 1636 dirty = False |
1555 | 1637 |
1556 # make it relative to the project root, if it starts with that path | 1638 # make it relative to the project root, if it starts with that path |
1557 # assume relative paths are relative to the project root | 1639 # assume relative paths are relative to the project root |
1558 newfn = self.getRelativePath(fn) if os.path.isabs(fn) else fn | 1640 newfn = self.getRelativePath(fn) if os.path.isabs(fn) else fn |
1559 newdir = os.path.dirname(newfn) | 1641 newdir = os.path.dirname(newfn) |
1560 | 1642 |
1561 if isSourceFile: | 1643 if isSourceFile: |
1562 filetype = "SOURCES" | 1644 filetype = "SOURCES" |
1563 else: | 1645 else: |
1564 filetype = "OTHERS" | 1646 filetype = "OTHERS" |
1565 bfn = os.path.basename(newfn) | 1647 bfn = os.path.basename(newfn) |
1566 if fnmatch.fnmatch(bfn, '*.ts') or fnmatch.fnmatch(bfn, '*.qm'): | 1648 if fnmatch.fnmatch(bfn, "*.ts") or fnmatch.fnmatch(bfn, "*.qm"): |
1567 filetype = "TRANSLATIONS" | 1649 filetype = "TRANSLATIONS" |
1568 else: | 1650 else: |
1569 for pattern in sorted(self.pdata["FILETYPES"].keys(), | 1651 for pattern in sorted(self.pdata["FILETYPES"].keys(), reverse=True): |
1570 reverse=True): | |
1571 if fnmatch.fnmatch(bfn, pattern): | 1652 if fnmatch.fnmatch(bfn, pattern): |
1572 filetype = self.pdata["FILETYPES"][pattern] | 1653 filetype = self.pdata["FILETYPES"][pattern] |
1573 break | 1654 break |
1574 | 1655 |
1575 if filetype == "__IGNORE__": | 1656 if filetype == "__IGNORE__": |
1576 return | 1657 return |
1577 | 1658 |
1578 if filetype in ["SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", | 1659 if filetype in ["SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", "RESOURCES"]: |
1579 "RESOURCES"]: | |
1580 if filetype == "SOURCES": | 1660 if filetype == "SOURCES": |
1581 if newfn not in self.pdata["SOURCES"]: | 1661 if newfn not in self.pdata["SOURCES"]: |
1582 self.pdata["SOURCES"].append(newfn) | 1662 self.pdata["SOURCES"].append(newfn) |
1583 self.projectSourceAdded.emit(newfn) | 1663 self.projectSourceAdded.emit(newfn) |
1584 updateModel and self.__model.addNewItem("SOURCES", newfn) | 1664 updateModel and self.__model.addNewItem("SOURCES", newfn) |
1595 updateModel and self.repopulateItem(newfn) | 1675 updateModel and self.repopulateItem(newfn) |
1596 elif filetype == "INTERFACES": | 1676 elif filetype == "INTERFACES": |
1597 if newfn not in self.pdata["INTERFACES"]: | 1677 if newfn not in self.pdata["INTERFACES"]: |
1598 self.pdata["INTERFACES"].append(newfn) | 1678 self.pdata["INTERFACES"].append(newfn) |
1599 self.projectInterfaceAdded.emit(newfn) | 1679 self.projectInterfaceAdded.emit(newfn) |
1600 (updateModel and | 1680 (updateModel and self.__model.addNewItem("INTERFACES", newfn)) |
1601 self.__model.addNewItem("INTERFACES", newfn)) | |
1602 dirty = True | 1681 dirty = True |
1603 else: | 1682 else: |
1604 updateModel and self.repopulateItem(newfn) | 1683 updateModel and self.repopulateItem(newfn) |
1605 elif filetype == "PROTOCOLS": | 1684 elif filetype == "PROTOCOLS": |
1606 if newfn not in self.pdata["PROTOCOLS"]: | 1685 if newfn not in self.pdata["PROTOCOLS"]: |
1607 self.pdata["PROTOCOLS"].append(newfn) | 1686 self.pdata["PROTOCOLS"].append(newfn) |
1608 self.projectProtocolAdded.emit(newfn) | 1687 self.projectProtocolAdded.emit(newfn) |
1609 (updateModel and | 1688 (updateModel and self.__model.addNewItem("PROTOCOLS", newfn)) |
1610 self.__model.addNewItem("PROTOCOLS", newfn)) | |
1611 dirty = True | 1689 dirty = True |
1612 else: | 1690 else: |
1613 updateModel and self.repopulateItem(newfn) | 1691 updateModel and self.repopulateItem(newfn) |
1614 elif filetype == "RESOURCES": | 1692 elif filetype == "RESOURCES": |
1615 if newfn not in self.pdata["RESOURCES"]: | 1693 if newfn not in self.pdata["RESOURCES"]: |
1627 updateModel and self.__model.addNewItem("TRANSLATIONS", newfn) | 1705 updateModel and self.__model.addNewItem("TRANSLATIONS", newfn) |
1628 self.projectLanguageAdded.emit(newfn) | 1706 self.projectLanguageAdded.emit(newfn) |
1629 dirty = True | 1707 dirty = True |
1630 else: | 1708 else: |
1631 updateModel and self.repopulateItem(newfn) | 1709 updateModel and self.repopulateItem(newfn) |
1632 else: # filetype == "OTHERS" | 1710 else: # filetype == "OTHERS" |
1633 if newfn not in self.pdata["OTHERS"]: | 1711 if newfn not in self.pdata["OTHERS"]: |
1634 self.pdata['OTHERS'].append(newfn) | 1712 self.pdata["OTHERS"].append(newfn) |
1635 self.othersAdded(newfn, updateModel) | 1713 self.othersAdded(newfn, updateModel) |
1636 dirty = True | 1714 dirty = True |
1637 else: | 1715 else: |
1638 updateModel and self.repopulateItem(newfn) | 1716 updateModel and self.repopulateItem(newfn) |
1639 if newdir not in self.otherssubdirs: | 1717 if newdir not in self.otherssubdirs: |
1640 self.otherssubdirs.append(newdir) | 1718 self.otherssubdirs.append(newdir) |
1641 | 1719 |
1642 if dirty: | 1720 if dirty: |
1643 self.setDirty(True) | 1721 self.setDirty(True) |
1644 | 1722 |
1645 @pyqtSlot() | 1723 @pyqtSlot() |
1646 def addFiles(self, fileTypeFilter=None, startdir=None): | 1724 def addFiles(self, fileTypeFilter=None, startdir=None): |
1647 """ | 1725 """ |
1648 Public slot used to add files to the project. | 1726 Public slot used to add files to the project. |
1649 | 1727 |
1650 @param fileTypeFilter filter to be used by the add file dialog | 1728 @param fileTypeFilter filter to be used by the add file dialog |
1651 @type str out of source, form, resource, interface, protocol, others | 1729 @type str out of source, form, resource, interface, protocol, others |
1652 @param startdir start directory for the selection dialog | 1730 @param startdir start directory for the selection dialog |
1653 @type str | 1731 @type str |
1654 """ | 1732 """ |
1655 if startdir is None: | 1733 if startdir is None: |
1656 startdir = self.ppath | 1734 startdir = self.ppath |
1657 from .AddFileDialog import AddFileDialog | 1735 from .AddFileDialog import AddFileDialog |
1658 dlg = AddFileDialog(self, self.parent(), fileTypeFilter, | 1736 |
1659 startdir=startdir) | 1737 dlg = AddFileDialog(self, self.parent(), fileTypeFilter, startdir=startdir) |
1660 if dlg.exec() == QDialog.DialogCode.Accepted: | 1738 if dlg.exec() == QDialog.DialogCode.Accepted: |
1661 fnames, target, isSource = dlg.getData() | 1739 fnames, target, isSource = dlg.getData() |
1662 if target != '': | 1740 if target != "": |
1663 for fn in fnames: | 1741 for fn in fnames: |
1664 targetfile = os.path.join(target, os.path.basename(fn)) | 1742 targetfile = os.path.join(target, os.path.basename(fn)) |
1665 if not Utilities.samepath(os.path.dirname(fn), target): | 1743 if not Utilities.samepath(os.path.dirname(fn), target): |
1666 try: | 1744 try: |
1667 if not os.path.isdir(target): | 1745 if not os.path.isdir(target): |
1668 os.makedirs(target) | 1746 os.makedirs(target) |
1669 | 1747 |
1670 if os.path.exists(targetfile): | 1748 if os.path.exists(targetfile): |
1671 res = EricMessageBox.yesNo( | 1749 res = EricMessageBox.yesNo( |
1672 self.ui, | 1750 self.ui, |
1673 self.tr("Add file"), | 1751 self.tr("Add file"), |
1674 self.tr( | 1752 self.tr( |
1675 "<p>The file <b>{0}</b> already" | 1753 "<p>The file <b>{0}</b> already" |
1676 " exists.</p><p>Overwrite it?</p>") | 1754 " exists.</p><p>Overwrite it?</p>" |
1677 .format(targetfile), | 1755 ).format(targetfile), |
1678 icon=EricMessageBox.Warning) | 1756 icon=EricMessageBox.Warning, |
1757 ) | |
1679 if not res: | 1758 if not res: |
1680 return # don't overwrite | 1759 return # don't overwrite |
1681 | 1760 |
1682 shutil.copy(fn, target) | 1761 shutil.copy(fn, target) |
1683 except OSError as why: | 1762 except OSError as why: |
1684 EricMessageBox.critical( | 1763 EricMessageBox.critical( |
1685 self.ui, | 1764 self.ui, |
1686 self.tr("Add file"), | 1765 self.tr("Add file"), |
1687 self.tr( | 1766 self.tr( |
1688 "<p>The selected file <b>{0}</b> could" | 1767 "<p>The selected file <b>{0}</b> could" |
1689 " not be added to <b>{1}</b>.</p>" | 1768 " not be added to <b>{1}</b>.</p>" |
1690 "<p>Reason: {2}</p>") | 1769 "<p>Reason: {2}</p>" |
1691 .format(fn, target, str(why))) | 1770 ).format(fn, target, str(why)), |
1771 ) | |
1692 continue | 1772 continue |
1693 | 1773 |
1694 self.appendFile(targetfile, | 1774 self.appendFile(targetfile, isSource or fileTypeFilter == "source") |
1695 isSource or fileTypeFilter == 'source') | |
1696 else: | 1775 else: |
1697 EricMessageBox.critical( | 1776 EricMessageBox.critical( |
1698 self.ui, | 1777 self.ui, |
1699 self.tr("Add file"), | 1778 self.tr("Add file"), |
1700 self.tr("The target directory must not be empty.")) | 1779 self.tr("The target directory must not be empty."), |
1701 | 1780 ) |
1781 | |
1702 def __addSingleDirectory(self, filetype, source, target, quiet=False): | 1782 def __addSingleDirectory(self, filetype, source, target, quiet=False): |
1703 """ | 1783 """ |
1704 Private method used to add all files of a single directory to the | 1784 Private method used to add all files of a single directory to the |
1705 project. | 1785 project. |
1706 | 1786 |
1707 @param filetype type of files to add (string) | 1787 @param filetype type of files to add (string) |
1708 @param source source directory (string) | 1788 @param source source directory (string) |
1709 @param target target directory (string) | 1789 @param target target directory (string) |
1710 @param quiet flag indicating quiet operations (boolean) | 1790 @param quiet flag indicating quiet operations (boolean) |
1711 """ | 1791 """ |
1715 for pattern, patterntype in list(self.pdata["FILETYPES"].items()): | 1795 for pattern, patterntype in list(self.pdata["FILETYPES"].items()): |
1716 if patterntype == filetype: | 1796 if patterntype == filetype: |
1717 patterns.append(pattern) | 1797 patterns.append(pattern) |
1718 elif patterntype == "__IGNORE__": | 1798 elif patterntype == "__IGNORE__": |
1719 ignorePatterns.append(pattern) | 1799 ignorePatterns.append(pattern) |
1720 | 1800 |
1721 files = [] | 1801 files = [] |
1722 for pattern in patterns: | 1802 for pattern in patterns: |
1723 sstring = "{0}{1}{2}".format(source, os.sep, pattern) | 1803 sstring = "{0}{1}{2}".format(source, os.sep, pattern) |
1724 files.extend(glob.glob(sstring)) | 1804 files.extend(glob.glob(sstring)) |
1725 | 1805 |
1726 if len(files) == 0: | 1806 if len(files) == 0: |
1727 if not quiet: | 1807 if not quiet: |
1728 EricMessageBox.information( | 1808 EricMessageBox.information( |
1729 self.ui, | 1809 self.ui, |
1730 self.tr("Add directory"), | 1810 self.tr("Add directory"), |
1731 self.tr( | 1811 self.tr( |
1732 "<p>The source directory doesn't contain" | 1812 "<p>The source directory doesn't contain" |
1733 " any files belonging to the selected category.</p>")) | 1813 " any files belonging to the selected category.</p>" |
1814 ), | |
1815 ) | |
1734 return | 1816 return |
1735 | 1817 |
1736 if ( | 1818 if not Utilities.samepath(target, source) and not os.path.isdir(target): |
1737 not Utilities.samepath(target, source) and | |
1738 not os.path.isdir(target) | |
1739 ): | |
1740 try: | 1819 try: |
1741 os.makedirs(target) | 1820 os.makedirs(target) |
1742 except OSError as why: | 1821 except OSError as why: |
1743 EricMessageBox.critical( | 1822 EricMessageBox.critical( |
1744 self.ui, | 1823 self.ui, |
1745 self.tr("Add directory"), | 1824 self.tr("Add directory"), |
1746 self.tr( | 1825 self.tr( |
1747 "<p>The target directory <b>{0}</b> could not be" | 1826 "<p>The target directory <b>{0}</b> could not be" |
1748 " created.</p><p>Reason: {1}</p>") | 1827 " created.</p><p>Reason: {1}</p>" |
1749 .format(target, str(why))) | 1828 ).format(target, str(why)), |
1829 ) | |
1750 return | 1830 return |
1751 | 1831 |
1752 for file in files: | 1832 for file in files: |
1753 for pattern in ignorePatterns: | 1833 for pattern in ignorePatterns: |
1754 if fnmatch.fnmatch(file, pattern): | 1834 if fnmatch.fnmatch(file, pattern): |
1755 continue | 1835 continue |
1756 | 1836 |
1757 targetfile = os.path.join(target, os.path.basename(file)) | 1837 targetfile = os.path.join(target, os.path.basename(file)) |
1758 if not Utilities.samepath(target, source): | 1838 if not Utilities.samepath(target, source): |
1759 try: | 1839 try: |
1760 if os.path.exists(targetfile): | 1840 if os.path.exists(targetfile): |
1761 res = EricMessageBox.yesNo( | 1841 res = EricMessageBox.yesNo( |
1762 self.ui, | 1842 self.ui, |
1763 self.tr("Add directory"), | 1843 self.tr("Add directory"), |
1764 self.tr( | 1844 self.tr( |
1765 "<p>The file <b>{0}</b> already exists.</p>" | 1845 "<p>The file <b>{0}</b> already exists.</p>" |
1766 "<p>Overwrite it?</p>") | 1846 "<p>Overwrite it?</p>" |
1767 .format(targetfile), | 1847 ).format(targetfile), |
1768 icon=EricMessageBox.Warning) | 1848 icon=EricMessageBox.Warning, |
1849 ) | |
1769 if not res: | 1850 if not res: |
1770 continue | 1851 continue |
1771 # don't overwrite, carry on with next file | 1852 # don't overwrite, carry on with next file |
1772 | 1853 |
1773 shutil.copy(file, target) | 1854 shutil.copy(file, target) |
1774 except OSError: | 1855 except OSError: |
1775 continue | 1856 continue |
1776 self.appendFile(targetfile) | 1857 self.appendFile(targetfile) |
1777 | 1858 |
1778 def __addRecursiveDirectory(self, filetype, source, target): | 1859 def __addRecursiveDirectory(self, filetype, source, target): |
1779 """ | 1860 """ |
1780 Private method used to add all files of a directory tree. | 1861 Private method used to add all files of a directory tree. |
1781 | 1862 |
1782 The tree is rooted at source to another one rooted at target. This | 1863 The tree is rooted at source to another one rooted at target. This |
1783 method decents down to the lowest subdirectory. | 1864 method decents down to the lowest subdirectory. |
1784 | 1865 |
1785 @param filetype type of files to add (string) | 1866 @param filetype type of files to add (string) |
1786 @param source source directory (string) | 1867 @param source source directory (string) |
1787 @param target target directory (string) | 1868 @param target target directory (string) |
1788 """ | 1869 """ |
1789 # first perform the addition of source | 1870 # first perform the addition of source |
1790 self.__addSingleDirectory(filetype, source, target, True) | 1871 self.__addSingleDirectory(filetype, source, target, True) |
1791 | 1872 |
1792 ignore_patterns = [pattern for pattern, filetype in | 1873 ignore_patterns = [ |
1793 self.pdata["FILETYPES"].items() | 1874 pattern |
1794 if filetype == '__IGNORE__'] | 1875 for pattern, filetype in self.pdata["FILETYPES"].items() |
1795 | 1876 if filetype == "__IGNORE__" |
1877 ] | |
1878 | |
1796 # now recurse into subdirectories | 1879 # now recurse into subdirectories |
1797 for name in os.listdir(source): | 1880 for name in os.listdir(source): |
1798 ns = os.path.join(source, name) | 1881 ns = os.path.join(source, name) |
1799 if os.path.isdir(ns): | 1882 if os.path.isdir(ns): |
1800 skip = False | 1883 skip = False |
1802 if fnmatch.fnmatch(name, ignore_pattern): | 1885 if fnmatch.fnmatch(name, ignore_pattern): |
1803 skip = True | 1886 skip = True |
1804 break | 1887 break |
1805 if skip: | 1888 if skip: |
1806 continue | 1889 continue |
1807 | 1890 |
1808 nt = os.path.join(target, name) | 1891 nt = os.path.join(target, name) |
1809 self.__addRecursiveDirectory(filetype, ns, nt) | 1892 self.__addRecursiveDirectory(filetype, ns, nt) |
1810 | 1893 |
1811 @pyqtSlot() | 1894 @pyqtSlot() |
1812 def addDirectory(self, fileTypeFilter=None, startdir=None): | 1895 def addDirectory(self, fileTypeFilter=None, startdir=None): |
1813 """ | 1896 """ |
1814 Public method used to add all files of a directory to the project. | 1897 Public method used to add all files of a directory to the project. |
1815 | 1898 |
1816 @param fileTypeFilter filter to be used by the add directory dialog | 1899 @param fileTypeFilter filter to be used by the add directory dialog |
1817 @type str out of source, form, resource, interface, protocol, others | 1900 @type str out of source, form, resource, interface, protocol, others |
1818 @param startdir start directory for the selection dialog | 1901 @param startdir start directory for the selection dialog |
1819 @type str | 1902 @type str |
1820 """ | 1903 """ |
1821 if startdir is None: | 1904 if startdir is None: |
1822 startdir = self.ppath | 1905 startdir = self.ppath |
1823 from .AddDirectoryDialog import AddDirectoryDialog | 1906 from .AddDirectoryDialog import AddDirectoryDialog |
1824 dlg = AddDirectoryDialog( | 1907 |
1825 self, fileTypeFilter, self.parent(), startdir=startdir) | 1908 dlg = AddDirectoryDialog(self, fileTypeFilter, self.parent(), startdir=startdir) |
1826 if dlg.exec() == QDialog.DialogCode.Accepted: | 1909 if dlg.exec() == QDialog.DialogCode.Accepted: |
1827 filetype, source, target, recursive = dlg.getData() | 1910 filetype, source, target, recursive = dlg.getData() |
1828 if target == '': | 1911 if target == "": |
1829 EricMessageBox.critical( | 1912 EricMessageBox.critical( |
1830 self.ui, | 1913 self.ui, |
1831 self.tr("Add directory"), | 1914 self.tr("Add directory"), |
1832 self.tr("The target directory must not be empty.")) | 1915 self.tr("The target directory must not be empty."), |
1916 ) | |
1833 return | 1917 return |
1834 | 1918 |
1835 if filetype == 'OTHERS': | 1919 if filetype == "OTHERS": |
1836 self.addToOthers(source) | 1920 self.addToOthers(source) |
1837 return | 1921 return |
1838 | 1922 |
1839 if source == '': | 1923 if source == "": |
1840 EricMessageBox.critical( | 1924 EricMessageBox.critical( |
1841 self.ui, | 1925 self.ui, |
1842 self.tr("Add directory"), | 1926 self.tr("Add directory"), |
1843 self.tr("The source directory must not be empty.")) | 1927 self.tr("The source directory must not be empty."), |
1928 ) | |
1844 return | 1929 return |
1845 | 1930 |
1846 if recursive: | 1931 if recursive: |
1847 self.__addRecursiveDirectory(filetype, source, target) | 1932 self.__addRecursiveDirectory(filetype, source, target) |
1848 else: | 1933 else: |
1849 self.__addSingleDirectory(filetype, source, target) | 1934 self.__addSingleDirectory(filetype, source, target) |
1850 | 1935 |
1851 def addToOthers(self, fn): | 1936 def addToOthers(self, fn): |
1852 """ | 1937 """ |
1853 Public method to add a file/directory to the OTHERS project data. | 1938 Public method to add a file/directory to the OTHERS project data. |
1854 | 1939 |
1855 @param fn file name or directory name to add (string) | 1940 @param fn file name or directory name to add (string) |
1856 """ | 1941 """ |
1857 if fn: | 1942 if fn: |
1858 # if it is below the project directory, make it relative to that | 1943 # if it is below the project directory, make it relative to that |
1859 fn = self.getRelativePath(fn) | 1944 fn = self.getRelativePath(fn) |
1860 | 1945 |
1861 # if it ends with the directory separator character, remove it | 1946 # if it ends with the directory separator character, remove it |
1862 if fn.endswith(os.sep): | 1947 if fn.endswith(os.sep): |
1863 fn = fn[:-1] | 1948 fn = fn[:-1] |
1864 | 1949 |
1865 if fn not in self.pdata["OTHERS"]: | 1950 if fn not in self.pdata["OTHERS"]: |
1866 self.pdata['OTHERS'].append(fn) | 1951 self.pdata["OTHERS"].append(fn) |
1867 self.othersAdded(fn) | 1952 self.othersAdded(fn) |
1868 self.setDirty(True) | 1953 self.setDirty(True) |
1869 | 1954 |
1870 if os.path.isdir(fn) and fn not in self.otherssubdirs: | 1955 if os.path.isdir(fn) and fn not in self.otherssubdirs: |
1871 self.otherssubdirs.append(fn) | 1956 self.otherssubdirs.append(fn) |
1872 | 1957 |
1873 def addSourceFiles(self): | 1958 def addSourceFiles(self): |
1874 """ | 1959 """ |
1875 Public slot to add source files to the current project. | 1960 Public slot to add source files to the current project. |
1876 """ | 1961 """ |
1877 self.addFiles('source') | 1962 self.addFiles("source") |
1878 | 1963 |
1879 def addUiFiles(self): | 1964 def addUiFiles(self): |
1880 """ | 1965 """ |
1881 Public slot to add forms to the current project. | 1966 Public slot to add forms to the current project. |
1882 """ | 1967 """ |
1883 self.addFiles('form') | 1968 self.addFiles("form") |
1884 | 1969 |
1885 def addIdlFiles(self): | 1970 def addIdlFiles(self): |
1886 """ | 1971 """ |
1887 Public slot to add IDL interfaces to the current project. | 1972 Public slot to add IDL interfaces to the current project. |
1888 """ | 1973 """ |
1889 self.addFiles('interface') | 1974 self.addFiles("interface") |
1890 | 1975 |
1891 def addProtoFiles(self): | 1976 def addProtoFiles(self): |
1892 """ | 1977 """ |
1893 Public slot to add protocol files to the current project. | 1978 Public slot to add protocol files to the current project. |
1894 """ | 1979 """ |
1895 self.addFiles('protocol') | 1980 self.addFiles("protocol") |
1896 | 1981 |
1897 def addResourceFiles(self): | 1982 def addResourceFiles(self): |
1898 """ | 1983 """ |
1899 Public slot to add Qt resources to the current project. | 1984 Public slot to add Qt resources to the current project. |
1900 """ | 1985 """ |
1901 self.addFiles('resource') | 1986 self.addFiles("resource") |
1902 | 1987 |
1903 def addOthersFiles(self): | 1988 def addOthersFiles(self): |
1904 """ | 1989 """ |
1905 Public slot to add files to the OTHERS project data. | 1990 Public slot to add files to the OTHERS project data. |
1906 """ | 1991 """ |
1907 self.addFiles('others') | 1992 self.addFiles("others") |
1908 | 1993 |
1909 def addSourceDir(self): | 1994 def addSourceDir(self): |
1910 """ | 1995 """ |
1911 Public slot to add all source files of a directory to the current | 1996 Public slot to add all source files of a directory to the current |
1912 project. | 1997 project. |
1913 """ | 1998 """ |
1914 self.addDirectory('source') | 1999 self.addDirectory("source") |
1915 | 2000 |
1916 def addUiDir(self): | 2001 def addUiDir(self): |
1917 """ | 2002 """ |
1918 Public slot to add all forms of a directory to the current project. | 2003 Public slot to add all forms of a directory to the current project. |
1919 """ | 2004 """ |
1920 self.addDirectory('form') | 2005 self.addDirectory("form") |
1921 | 2006 |
1922 def addIdlDir(self): | 2007 def addIdlDir(self): |
1923 """ | 2008 """ |
1924 Public slot to add all IDL interfaces of a directory to the current | 2009 Public slot to add all IDL interfaces of a directory to the current |
1925 project. | 2010 project. |
1926 """ | 2011 """ |
1927 self.addDirectory('interface') | 2012 self.addDirectory("interface") |
1928 | 2013 |
1929 def addProtoDir(self): | 2014 def addProtoDir(self): |
1930 """ | 2015 """ |
1931 Public slot to add all protocol files of a directory to the current | 2016 Public slot to add all protocol files of a directory to the current |
1932 project. | 2017 project. |
1933 """ | 2018 """ |
1934 self.addDirectory('protocol') | 2019 self.addDirectory("protocol") |
1935 | 2020 |
1936 def addResourceDir(self): | 2021 def addResourceDir(self): |
1937 """ | 2022 """ |
1938 Public slot to add all Qt resource files of a directory to the current | 2023 Public slot to add all Qt resource files of a directory to the current |
1939 project. | 2024 project. |
1940 """ | 2025 """ |
1941 self.addDirectory('resource') | 2026 self.addDirectory("resource") |
1942 | 2027 |
1943 def addOthersDir(self): | 2028 def addOthersDir(self): |
1944 """ | 2029 """ |
1945 Public slot to add a directory to the OTHERS project data. | 2030 Public slot to add a directory to the OTHERS project data. |
1946 """ | 2031 """ |
1947 self.addDirectory('others') | 2032 self.addDirectory("others") |
1948 | 2033 |
1949 def renameMainScript(self, oldfn, newfn): | 2034 def renameMainScript(self, oldfn, newfn): |
1950 """ | 2035 """ |
1951 Public method to rename the main script. | 2036 Public method to rename the main script. |
1952 | 2037 |
1953 @param oldfn old filename (string) | 2038 @param oldfn old filename (string) |
1954 @param newfn new filename of the main script (string) | 2039 @param newfn new filename of the main script (string) |
1955 """ | 2040 """ |
1956 if self.pdata["MAINSCRIPT"]: | 2041 if self.pdata["MAINSCRIPT"]: |
1957 ofn = self.getRelativePath(oldfn) | 2042 ofn = self.getRelativePath(oldfn) |
1958 if ofn != self.pdata["MAINSCRIPT"]: | 2043 if ofn != self.pdata["MAINSCRIPT"]: |
1959 return | 2044 return |
1960 | 2045 |
1961 fn = self.getRelativePath(newfn) | 2046 fn = self.getRelativePath(newfn) |
1962 self.pdata["MAINSCRIPT"] = fn | 2047 self.pdata["MAINSCRIPT"] = fn |
1963 self.setDirty(True) | 2048 self.setDirty(True) |
1964 | 2049 |
1965 def renameFile(self, oldfn, newfn=None): | 2050 def renameFile(self, oldfn, newfn=None): |
1966 """ | 2051 """ |
1967 Public slot to rename a file of the project. | 2052 Public slot to rename a file of the project. |
1968 | 2053 |
1969 @param oldfn old filename of the file (string) | 2054 @param oldfn old filename of the file (string) |
1970 @param newfn new filename of the file (string) | 2055 @param newfn new filename of the file (string) |
1971 @return flag indicating success | 2056 @return flag indicating success |
1972 """ | 2057 """ |
1973 fn = self.getRelativePath(oldfn) | 2058 fn = self.getRelativePath(oldfn) |
1974 isSourceFile = fn in self.pdata["SOURCES"] | 2059 isSourceFile = fn in self.pdata["SOURCES"] |
1975 | 2060 |
1976 if newfn is None: | 2061 if newfn is None: |
1977 newfn = EricFileDialog.getSaveFileName( | 2062 newfn = EricFileDialog.getSaveFileName( |
1978 None, | 2063 None, |
1979 self.tr("Rename file"), | 2064 self.tr("Rename file"), |
1980 oldfn, | 2065 oldfn, |
1981 "", | 2066 "", |
1982 EricFileDialog.DontConfirmOverwrite) | 2067 EricFileDialog.DontConfirmOverwrite, |
2068 ) | |
1983 if not newfn: | 2069 if not newfn: |
1984 return False | 2070 return False |
1985 newfn = Utilities.toNativeSeparators(newfn) | 2071 newfn = Utilities.toNativeSeparators(newfn) |
1986 | 2072 |
1987 if os.path.exists(newfn): | 2073 if os.path.exists(newfn): |
1988 res = EricMessageBox.yesNo( | 2074 res = EricMessageBox.yesNo( |
1989 self.ui, | 2075 self.ui, |
1990 self.tr("Rename File"), | 2076 self.tr("Rename File"), |
1991 self.tr("""<p>The file <b>{0}</b> already exists.""" | 2077 self.tr( |
1992 """ Overwrite it?</p>""") | 2078 """<p>The file <b>{0}</b> already exists.""" |
1993 .format(newfn), | 2079 """ Overwrite it?</p>""" |
1994 icon=EricMessageBox.Warning) | 2080 ).format(newfn), |
2081 icon=EricMessageBox.Warning, | |
2082 ) | |
1995 if not res: | 2083 if not res: |
1996 return False | 2084 return False |
1997 | 2085 |
1998 try: | 2086 try: |
1999 os.rename(oldfn, newfn) | 2087 os.rename(oldfn, newfn) |
2000 except OSError as msg: | 2088 except OSError as msg: |
2001 EricMessageBox.critical( | 2089 EricMessageBox.critical( |
2002 self.ui, | 2090 self.ui, |
2003 self.tr("Rename File"), | 2091 self.tr("Rename File"), |
2004 self.tr( | 2092 self.tr( |
2005 """<p>The file <b>{0}</b> could not be renamed.<br />""" | 2093 """<p>The file <b>{0}</b> could not be renamed.<br />""" |
2006 """Reason: {1}</p>""").format(oldfn, str(msg))) | 2094 """Reason: {1}</p>""" |
2095 ).format(oldfn, str(msg)), | |
2096 ) | |
2007 return False | 2097 return False |
2008 | 2098 |
2009 if ( | 2099 if ( |
2010 fn in self.pdata["SOURCES"] or | 2100 fn in self.pdata["SOURCES"] |
2011 fn in self.pdata["FORMS"] or | 2101 or fn in self.pdata["FORMS"] |
2012 fn in self.pdata["TRANSLATIONS"] or | 2102 or fn in self.pdata["TRANSLATIONS"] |
2013 fn in self.pdata["INTERFACES"] or | 2103 or fn in self.pdata["INTERFACES"] |
2014 fn in self.pdata["PROTOCOLS"] or | 2104 or fn in self.pdata["PROTOCOLS"] |
2015 fn in self.pdata["RESOURCES"] or | 2105 or fn in self.pdata["RESOURCES"] |
2016 fn in self.pdata["OTHERS"] | 2106 or fn in self.pdata["OTHERS"] |
2017 ): | 2107 ): |
2018 self.renameFileInPdata(oldfn, newfn, isSourceFile) | 2108 self.renameFileInPdata(oldfn, newfn, isSourceFile) |
2019 | 2109 |
2020 return True | 2110 return True |
2021 | 2111 |
2022 def renameFileInPdata(self, oldname, newname, isSourceFile=False): | 2112 def renameFileInPdata(self, oldname, newname, isSourceFile=False): |
2023 """ | 2113 """ |
2024 Public method to rename a file in the pdata structure. | 2114 Public method to rename a file in the pdata structure. |
2025 | 2115 |
2026 @param oldname old filename (string) | 2116 @param oldname old filename (string) |
2027 @param newname new filename (string) | 2117 @param newname new filename (string) |
2028 @param isSourceFile flag indicating that this is a source file | 2118 @param isSourceFile flag indicating that this is a source file |
2029 even if it doesn't have the source extension (boolean) | 2119 even if it doesn't have the source extension (boolean) |
2030 """ | 2120 """ |
2036 self.__model.renameItem(fn, newname) | 2126 self.__model.renameItem(fn, newname) |
2037 else: | 2127 else: |
2038 self.removeFile(oldname) | 2128 self.removeFile(oldname) |
2039 self.appendFile(newname, isSourceFile) | 2129 self.appendFile(newname, isSourceFile) |
2040 self.projectFileRenamed.emit(oldname, newname) | 2130 self.projectFileRenamed.emit(oldname, newname) |
2041 | 2131 |
2042 self.renameMainScript(fn, newname) | 2132 self.renameMainScript(fn, newname) |
2043 | 2133 |
2044 def getFiles(self, start): | 2134 def getFiles(self, start): |
2045 """ | 2135 """ |
2046 Public method to get all files starting with a common prefix. | 2136 Public method to get all files starting with a common prefix. |
2047 | 2137 |
2048 @param start prefix (string) | 2138 @param start prefix (string) |
2049 @return list of files starting with a common prefix (list of strings) | 2139 @return list of files starting with a common prefix (list of strings) |
2050 """ | 2140 """ |
2051 filelist = [] | 2141 filelist = [] |
2052 start = self.getRelativePath(start) | 2142 start = self.getRelativePath(start) |
2053 for key in ["SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", "RESOURCES", | 2143 for key in [ |
2054 "OTHERS"]: | 2144 "SOURCES", |
2145 "FORMS", | |
2146 "INTERFACES", | |
2147 "PROTOCOLS", | |
2148 "RESOURCES", | |
2149 "OTHERS", | |
2150 ]: | |
2055 for entry in self.pdata[key][:]: | 2151 for entry in self.pdata[key][:]: |
2056 if entry.startswith(start): | 2152 if entry.startswith(start): |
2057 filelist.append(os.path.join(self.ppath, entry)) | 2153 filelist.append(os.path.join(self.ppath, entry)) |
2058 return filelist | 2154 return filelist |
2059 | 2155 |
2060 def __reorganizeFiles(self): | 2156 def __reorganizeFiles(self): |
2061 """ | 2157 """ |
2062 Private method to reorganize files stored in the project. | 2158 Private method to reorganize files stored in the project. |
2063 """ | 2159 """ |
2064 reorganized = False | 2160 reorganized = False |
2065 | 2161 |
2066 # init data store for the reorganization | 2162 # init data store for the reorganization |
2067 newPdata = {} | 2163 newPdata = {} |
2068 for key in ["SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", "RESOURCES", | 2164 for key in [ |
2069 "OTHERS", "TRANSLATIONS"]: | 2165 "SOURCES", |
2166 "FORMS", | |
2167 "INTERFACES", | |
2168 "PROTOCOLS", | |
2169 "RESOURCES", | |
2170 "OTHERS", | |
2171 "TRANSLATIONS", | |
2172 ]: | |
2070 newPdata[key] = [] | 2173 newPdata[key] = [] |
2071 | 2174 |
2072 # iterate over all files checking for a reassignment | 2175 # iterate over all files checking for a reassignment |
2073 for key in ["SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", "RESOURCES", | 2176 for key in [ |
2074 "OTHERS", "TRANSLATIONS"]: | 2177 "SOURCES", |
2178 "FORMS", | |
2179 "INTERFACES", | |
2180 "PROTOCOLS", | |
2181 "RESOURCES", | |
2182 "OTHERS", | |
2183 "TRANSLATIONS", | |
2184 ]: | |
2075 for fn in self.pdata[key][:]: | 2185 for fn in self.pdata[key][:]: |
2076 filetype = key | 2186 filetype = key |
2077 bfn = os.path.basename(fn) | 2187 bfn = os.path.basename(fn) |
2078 for pattern in sorted(self.pdata["FILETYPES"].keys(), | 2188 for pattern in sorted(self.pdata["FILETYPES"].keys(), reverse=True): |
2079 reverse=True): | |
2080 if fnmatch.fnmatch(bfn, pattern): | 2189 if fnmatch.fnmatch(bfn, pattern): |
2081 filetype = self.pdata["FILETYPES"][pattern] | 2190 filetype = self.pdata["FILETYPES"][pattern] |
2082 break | 2191 break |
2083 | 2192 |
2084 if filetype != "__IGNORE__": | 2193 if filetype != "__IGNORE__": |
2085 newPdata[filetype].append(fn) | 2194 newPdata[filetype].append(fn) |
2086 if filetype != key: | 2195 if filetype != key: |
2087 reorganized = True | 2196 reorganized = True |
2088 | 2197 |
2089 if reorganized: | 2198 if reorganized: |
2090 # copy the reorganized files back to the project | 2199 # copy the reorganized files back to the project |
2091 for key in ["SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", | 2200 for key in [ |
2092 "RESOURCES", "OTHERS", "TRANSLATIONS"]: | 2201 "SOURCES", |
2202 "FORMS", | |
2203 "INTERFACES", | |
2204 "PROTOCOLS", | |
2205 "RESOURCES", | |
2206 "OTHERS", | |
2207 "TRANSLATIONS", | |
2208 ]: | |
2093 self.pdata[key] = newPdata[key][:] | 2209 self.pdata[key] = newPdata[key][:] |
2094 | 2210 |
2095 # repopulate the model | 2211 # repopulate the model |
2096 self.__model.projectClosed(False) | 2212 self.__model.projectClosed(False) |
2097 self.__model.projectOpened() | 2213 self.__model.projectOpened() |
2098 | 2214 |
2099 def copyDirectory(self, olddn, newdn): | 2215 def copyDirectory(self, olddn, newdn): |
2100 """ | 2216 """ |
2101 Public slot to copy a directory. | 2217 Public slot to copy a directory. |
2102 | 2218 |
2103 @param olddn original directory name (string) | 2219 @param olddn original directory name (string) |
2104 @param newdn new directory name (string) | 2220 @param newdn new directory name (string) |
2105 """ | 2221 """ |
2106 olddn = self.getRelativePath(olddn) | 2222 olddn = self.getRelativePath(olddn) |
2107 newdn = self.getRelativePath(newdn) | 2223 newdn = self.getRelativePath(newdn) |
2108 for key in ["SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", "RESOURCES", | 2224 for key in [ |
2109 "OTHERS"]: | 2225 "SOURCES", |
2226 "FORMS", | |
2227 "INTERFACES", | |
2228 "PROTOCOLS", | |
2229 "RESOURCES", | |
2230 "OTHERS", | |
2231 ]: | |
2110 for entry in self.pdata[key][:]: | 2232 for entry in self.pdata[key][:]: |
2111 if entry.startswith(olddn): | 2233 if entry.startswith(olddn): |
2112 entry = entry.replace(olddn, newdn) | 2234 entry = entry.replace(olddn, newdn) |
2113 self.appendFile(os.path.join(self.ppath, entry), | 2235 self.appendFile(os.path.join(self.ppath, entry), key == "SOURCES") |
2114 key == "SOURCES") | |
2115 self.setDirty(True) | 2236 self.setDirty(True) |
2116 | 2237 |
2117 def moveDirectory(self, olddn, newdn): | 2238 def moveDirectory(self, olddn, newdn): |
2118 """ | 2239 """ |
2119 Public slot to move a directory. | 2240 Public slot to move a directory. |
2120 | 2241 |
2121 @param olddn old directory name (string) | 2242 @param olddn old directory name (string) |
2122 @param newdn new directory name (string) | 2243 @param newdn new directory name (string) |
2123 """ | 2244 """ |
2124 olddn = self.getRelativePath(olddn) | 2245 olddn = self.getRelativePath(olddn) |
2125 newdn = self.getRelativePath(newdn) | 2246 newdn = self.getRelativePath(newdn) |
2126 typeStrings = [] | 2247 typeStrings = [] |
2127 for key in ["SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", "RESOURCES", | 2248 for key in [ |
2128 "OTHERS"]: | 2249 "SOURCES", |
2250 "FORMS", | |
2251 "INTERFACES", | |
2252 "PROTOCOLS", | |
2253 "RESOURCES", | |
2254 "OTHERS", | |
2255 ]: | |
2129 for entry in self.pdata[key][:]: | 2256 for entry in self.pdata[key][:]: |
2130 if entry.startswith(olddn): | 2257 if entry.startswith(olddn): |
2131 if key not in typeStrings: | 2258 if key not in typeStrings: |
2132 typeStrings.append(key) | 2259 typeStrings.append(key) |
2133 self.pdata[key].remove(entry) | 2260 self.pdata[key].remove(entry) |
2147 del typeStrings[0] | 2274 del typeStrings[0] |
2148 self.__model.addNewItem(typeString, newdn, typeStrings) | 2275 self.__model.addNewItem(typeString, newdn, typeStrings) |
2149 else: | 2276 else: |
2150 self.__model.renameItem(olddn, self.getAbsolutePath(newdn)) | 2277 self.__model.renameItem(olddn, self.getAbsolutePath(newdn)) |
2151 self.directoryRemoved.emit(olddn) | 2278 self.directoryRemoved.emit(olddn) |
2152 | 2279 |
2153 def removeFile(self, fn, updateModel=True): | 2280 def removeFile(self, fn, updateModel=True): |
2154 """ | 2281 """ |
2155 Public slot to remove a file from the project. | 2282 Public slot to remove a file from the project. |
2156 | 2283 |
2157 The file is not deleted from the project directory. | 2284 The file is not deleted from the project directory. |
2158 | 2285 |
2159 @param fn filename to be removed from the project | 2286 @param fn filename to be removed from the project |
2160 @param updateModel flag indicating an update of the model is | 2287 @param updateModel flag indicating an update of the model is |
2161 requested (boolean) | 2288 requested (boolean) |
2162 """ | 2289 """ |
2163 fn = self.getRelativePath(fn) | 2290 fn = self.getRelativePath(fn) |
2186 else: | 2313 else: |
2187 dirty = False | 2314 dirty = False |
2188 updateModel and self.__model.removeItem(fn) | 2315 updateModel and self.__model.removeItem(fn) |
2189 if dirty: | 2316 if dirty: |
2190 self.setDirty(True) | 2317 self.setDirty(True) |
2191 | 2318 |
2192 def removeDirectory(self, dn): | 2319 def removeDirectory(self, dn): |
2193 """ | 2320 """ |
2194 Public method to remove a directory from the project. | 2321 Public method to remove a directory from the project. |
2195 | 2322 |
2196 The directory is not deleted from the project directory. | 2323 The directory is not deleted from the project directory. |
2197 | 2324 |
2198 @param dn directory name to be removed from the project | 2325 @param dn directory name to be removed from the project |
2199 """ | 2326 """ |
2200 dirty = False | 2327 dirty = False |
2201 dn = self.getRelativePath(dn) | 2328 dn = self.getRelativePath(dn) |
2202 for entry in self.pdata["OTHERS"][:]: | 2329 for entry in self.pdata["OTHERS"][:]: |
2203 if entry.startswith(dn): | 2330 if entry.startswith(dn): |
2204 self.pdata["OTHERS"].remove(entry) | 2331 self.pdata["OTHERS"].remove(entry) |
2205 dirty = True | 2332 dirty = True |
2206 dn2 = dn if dn.endswith(os.sep) else dn + os.sep | 2333 dn2 = dn if dn.endswith(os.sep) else dn + os.sep |
2207 for key in ["SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", "RESOURCES", | 2334 for key in [ |
2208 "TRANSLATIONS", ]: | 2335 "SOURCES", |
2336 "FORMS", | |
2337 "INTERFACES", | |
2338 "PROTOCOLS", | |
2339 "RESOURCES", | |
2340 "TRANSLATIONS", | |
2341 ]: | |
2209 for entry in self.pdata[key][:]: | 2342 for entry in self.pdata[key][:]: |
2210 if entry.startswith(dn2): | 2343 if entry.startswith(dn2): |
2211 self.pdata[key].remove(entry) | 2344 self.pdata[key].remove(entry) |
2212 dirty = True | 2345 dirty = True |
2213 self.__model.removeItem(dn) | 2346 self.__model.removeItem(dn) |
2214 if dirty: | 2347 if dirty: |
2215 self.setDirty(True) | 2348 self.setDirty(True) |
2216 self.directoryRemoved.emit(dn) | 2349 self.directoryRemoved.emit(dn) |
2217 | 2350 |
2218 def deleteFile(self, fn): | 2351 def deleteFile(self, fn): |
2219 """ | 2352 """ |
2220 Public method to delete a file from the project directory. | 2353 Public method to delete a file from the project directory. |
2221 | 2354 |
2222 @param fn filename to be deleted from the project | 2355 @param fn filename to be deleted from the project |
2223 @return flag indicating success (boolean) | 2356 @return flag indicating success (boolean) |
2224 """ | 2357 """ |
2225 try: | 2358 try: |
2226 from send2trash import send2trash as s2t | 2359 from send2trash import send2trash as s2t |
2227 except ImportError: | 2360 except ImportError: |
2228 s2t = os.remove | 2361 s2t = os.remove |
2229 | 2362 |
2230 try: | 2363 try: |
2231 s2t(os.path.join(self.ppath, fn)) | 2364 s2t(os.path.join(self.ppath, fn)) |
2232 path, ext = os.path.splitext(fn) | 2365 path, ext = os.path.splitext(fn) |
2233 if ext == '.ui': | 2366 if ext == ".ui": |
2234 fn2 = os.path.join(self.ppath, '{0}.h'.format(fn)) | 2367 fn2 = os.path.join(self.ppath, "{0}.h".format(fn)) |
2235 if os.path.isfile(fn2): | 2368 if os.path.isfile(fn2): |
2236 s2t(fn2) | 2369 s2t(fn2) |
2237 head, tail = os.path.split(path) | 2370 head, tail = os.path.split(path) |
2238 for ext in ['.pyc', '.pyo']: | 2371 for ext in [".pyc", ".pyo"]: |
2239 fn2 = os.path.join(self.ppath, path + ext) | 2372 fn2 = os.path.join(self.ppath, path + ext) |
2240 if os.path.isfile(fn2): | 2373 if os.path.isfile(fn2): |
2241 s2t(fn2) | 2374 s2t(fn2) |
2242 pat = os.path.join( | 2375 pat = os.path.join( |
2243 self.ppath, head, | 2376 self.ppath, head, "__pycache__", "{0}.*{1}".format(tail, ext) |
2244 "__pycache__", "{0}.*{1}".format(tail, ext)) | 2377 ) |
2245 for f in glob.glob(pat): | 2378 for f in glob.glob(pat): |
2246 s2t(f) | 2379 s2t(f) |
2247 except OSError as err: | 2380 except OSError as err: |
2248 EricMessageBox.critical( | 2381 EricMessageBox.critical( |
2249 self.ui, | 2382 self.ui, |
2250 self.tr("Delete file"), | 2383 self.tr("Delete file"), |
2251 self.tr( | 2384 self.tr( |
2252 "<p>The selected file <b>{0}</b> could not be" | 2385 "<p>The selected file <b>{0}</b> could not be" |
2253 " deleted.</p><p>Reason: {1}</p>").format( | 2386 " deleted.</p><p>Reason: {1}</p>" |
2254 fn, str(err))) | 2387 ).format(fn, str(err)), |
2388 ) | |
2255 return False | 2389 return False |
2256 | 2390 |
2257 self.removeFile(fn) | 2391 self.removeFile(fn) |
2258 if ext == '.ui': | 2392 if ext == ".ui": |
2259 self.removeFile(fn + '.h') | 2393 self.removeFile(fn + ".h") |
2260 return True | 2394 return True |
2261 | 2395 |
2262 def deleteDirectory(self, dn): | 2396 def deleteDirectory(self, dn): |
2263 """ | 2397 """ |
2264 Public method to delete a directory from the project directory. | 2398 Public method to delete a directory from the project directory. |
2265 | 2399 |
2266 @param dn directory name to be removed from the project | 2400 @param dn directory name to be removed from the project |
2267 @return flag indicating success (boolean) | 2401 @return flag indicating success (boolean) |
2268 """ | 2402 """ |
2269 if not os.path.isabs(dn): | 2403 if not os.path.isabs(dn): |
2270 dn = os.path.join(self.ppath, dn) | 2404 dn = os.path.join(self.ppath, dn) |
2271 try: | 2405 try: |
2272 try: | 2406 try: |
2273 from send2trash import send2trash | 2407 from send2trash import send2trash |
2408 | |
2274 send2trash(dn) | 2409 send2trash(dn) |
2275 except ImportError: | 2410 except ImportError: |
2276 shutil.rmtree(dn, True) | 2411 shutil.rmtree(dn, True) |
2277 except OSError as err: | 2412 except OSError as err: |
2278 EricMessageBox.critical( | 2413 EricMessageBox.critical( |
2279 self.ui, | 2414 self.ui, |
2280 self.tr("Delete directory"), | 2415 self.tr("Delete directory"), |
2281 self.tr( | 2416 self.tr( |
2282 "<p>The selected directory <b>{0}</b> could not be" | 2417 "<p>The selected directory <b>{0}</b> could not be" |
2283 " deleted.</p><p>Reason: {1}</p>").format(dn, str(err))) | 2418 " deleted.</p><p>Reason: {1}</p>" |
2419 ).format(dn, str(err)), | |
2420 ) | |
2284 return False | 2421 return False |
2285 | 2422 |
2286 self.removeDirectory(dn) | 2423 self.removeDirectory(dn) |
2287 return True | 2424 return True |
2288 | 2425 |
2289 def hasEntry(self, fn): | 2426 def hasEntry(self, fn): |
2290 """ | 2427 """ |
2291 Public method to check the project for a file. | 2428 Public method to check the project for a file. |
2292 | 2429 |
2293 @param fn filename to be checked (string) | 2430 @param fn filename to be checked (string) |
2294 @return flag indicating, if the project contains the file (boolean) | 2431 @return flag indicating, if the project contains the file (boolean) |
2295 """ | 2432 """ |
2296 fn = self.getRelativePath(fn) | 2433 fn = self.getRelativePath(fn) |
2297 return ( | 2434 return ( |
2298 fn in self.pdata["SOURCES"] or | 2435 fn in self.pdata["SOURCES"] |
2299 fn in self.pdata["FORMS"] or | 2436 or fn in self.pdata["FORMS"] |
2300 fn in self.pdata["INTERFACES"] or | 2437 or fn in self.pdata["INTERFACES"] |
2301 fn in self.pdata["PROTOCOLS"] or | 2438 or fn in self.pdata["PROTOCOLS"] |
2302 fn in self.pdata["RESOURCES"] or | 2439 or fn in self.pdata["RESOURCES"] |
2303 fn in self.pdata["OTHERS"] | 2440 or fn in self.pdata["OTHERS"] |
2304 ) | 2441 ) |
2305 | 2442 |
2306 def createNewProject(self): | 2443 def createNewProject(self): |
2307 """ | 2444 """ |
2308 Public slot to built a new project. | 2445 Public slot to built a new project. |
2309 | 2446 |
2310 This method displays the new project dialog and initializes | 2447 This method displays the new project dialog and initializes |
2311 the project object with the data entered. | 2448 the project object with the data entered. |
2312 """ | 2449 """ |
2313 if not self.checkDirty(): | 2450 if not self.checkDirty(): |
2314 return | 2451 return |
2315 | 2452 |
2316 from .PropertiesDialog import PropertiesDialog | 2453 from .PropertiesDialog import PropertiesDialog |
2454 | |
2317 dlg = PropertiesDialog(self, True) | 2455 dlg = PropertiesDialog(self, True) |
2318 if dlg.exec() == QDialog.DialogCode.Accepted: | 2456 if dlg.exec() == QDialog.DialogCode.Accepted: |
2319 self.closeProject() | 2457 self.closeProject() |
2320 dlg.storeData() | 2458 dlg.storeData() |
2321 self.pdata["VCS"] = 'None' | 2459 self.pdata["VCS"] = "None" |
2322 self.opened = True | 2460 self.opened = True |
2323 if not self.pdata["FILETYPES"]: | 2461 if not self.pdata["FILETYPES"]: |
2324 self.initFileTypes() | 2462 self.initFileTypes() |
2325 self.setDirty(True) | 2463 self.setDirty(True) |
2326 self.closeAct.setEnabled(True) | 2464 self.closeAct.setEnabled(True) |
2337 self.menuCheckAct.setEnabled(True) | 2475 self.menuCheckAct.setEnabled(True) |
2338 self.menuShowAct.setEnabled(True) | 2476 self.menuShowAct.setEnabled(True) |
2339 self.menuDiagramAct.setEnabled(True) | 2477 self.menuDiagramAct.setEnabled(True) |
2340 self.menuApidocAct.setEnabled(True) | 2478 self.menuApidocAct.setEnabled(True) |
2341 self.menuPackagersAct.setEnabled(True) | 2479 self.menuPackagersAct.setEnabled(True) |
2342 self.pluginGrp.setEnabled( | 2480 self.pluginGrp.setEnabled(self.pdata["PROJECTTYPE"] in ["E7Plugin"]) |
2343 self.pdata["PROJECTTYPE"] in ["E7Plugin"]) | 2481 self.addLanguageAct.setEnabled(bool(self.pdata["TRANSLATIONPATTERN"])) |
2344 self.addLanguageAct.setEnabled( | 2482 self.makeGrp.setEnabled(self.pdata["MAKEPARAMS"]["MakeEnabled"]) |
2345 bool(self.pdata["TRANSLATIONPATTERN"])) | 2483 self.menuMakeAct.setEnabled(self.pdata["MAKEPARAMS"]["MakeEnabled"]) |
2346 self.makeGrp.setEnabled( | |
2347 self.pdata["MAKEPARAMS"]["MakeEnabled"]) | |
2348 self.menuMakeAct.setEnabled( | |
2349 self.pdata["MAKEPARAMS"]["MakeEnabled"]) | |
2350 self.menuOtherToolsAct.setEnabled(True) | 2484 self.menuOtherToolsAct.setEnabled(True) |
2351 self.menuFormattingAct.setEnabled(True) | 2485 self.menuFormattingAct.setEnabled(True) |
2352 | 2486 |
2353 self.projectAboutToBeCreated.emit() | 2487 self.projectAboutToBeCreated.emit() |
2354 | 2488 |
2355 hashStr = str(QCryptographicHash.hash( | 2489 hashStr = str( |
2356 QByteArray(self.ppath.encode("utf-8")), | 2490 QCryptographicHash.hash( |
2357 QCryptographicHash.Algorithm.Sha1).toHex(), | 2491 QByteArray(self.ppath.encode("utf-8")), |
2358 encoding="utf-8") | 2492 QCryptographicHash.Algorithm.Sha1, |
2493 ).toHex(), | |
2494 encoding="utf-8", | |
2495 ) | |
2359 self.pdata["HASH"] = hashStr | 2496 self.pdata["HASH"] = hashStr |
2360 | 2497 |
2361 if self.pdata["PROGLANGUAGE"] == "MicroPython": | 2498 if self.pdata["PROGLANGUAGE"] == "MicroPython": |
2362 # change the lexer association for *.py files | 2499 # change the lexer association for *.py files |
2363 self.pdata["LEXERASSOCS"] = { | 2500 self.pdata["LEXERASSOCS"] = { |
2364 "*.py": "MicroPython", | 2501 "*.py": "MicroPython", |
2365 } | 2502 } |
2366 | 2503 |
2367 # create the project directory if it doesn't exist already | 2504 # create the project directory if it doesn't exist already |
2368 if not os.path.isdir(self.ppath): | 2505 if not os.path.isdir(self.ppath): |
2369 try: | 2506 try: |
2370 os.makedirs(self.ppath) | 2507 os.makedirs(self.ppath) |
2371 except OSError: | 2508 except OSError: |
2372 EricMessageBox.critical( | 2509 EricMessageBox.critical( |
2373 self.ui, | 2510 self.ui, |
2374 self.tr("Create project directory"), | 2511 self.tr("Create project directory"), |
2375 self.tr( | 2512 self.tr( |
2376 "<p>The project directory <b>{0}</b> could not" | 2513 "<p>The project directory <b>{0}</b> could not" |
2377 " be created.</p>") | 2514 " be created.</p>" |
2378 .format(self.ppath)) | 2515 ).format(self.ppath), |
2516 ) | |
2379 self.vcs = self.initVCS() | 2517 self.vcs = self.initVCS() |
2380 return | 2518 return |
2381 | 2519 |
2382 # create an empty __init__.py file to make it a Python package | 2520 # create an empty __init__.py file to make it a Python package |
2383 # (only for Python and Python3) | 2521 # (only for Python and Python3) |
2384 if self.pdata["PROGLANGUAGE"] in [ | 2522 if self.pdata["PROGLANGUAGE"] in ["Python3", "MicroPython"]: |
2385 "Python3", "MicroPython" | |
2386 ]: | |
2387 fn = os.path.join(self.ppath, "__init__.py") | 2523 fn = os.path.join(self.ppath, "__init__.py") |
2388 with open(fn, "w", encoding="utf-8"): | 2524 with open(fn, "w", encoding="utf-8"): |
2389 pass | 2525 pass |
2390 self.appendFile(fn, True) | 2526 self.appendFile(fn, True) |
2391 | 2527 |
2392 # create an empty main script file, if a name was given | 2528 # create an empty main script file, if a name was given |
2393 if self.pdata["MAINSCRIPT"]: | 2529 if self.pdata["MAINSCRIPT"]: |
2394 if not os.path.isabs(self.pdata["MAINSCRIPT"]): | 2530 if not os.path.isabs(self.pdata["MAINSCRIPT"]): |
2395 ms = os.path.join( | 2531 ms = os.path.join(self.ppath, self.pdata["MAINSCRIPT"]) |
2396 self.ppath, self.pdata["MAINSCRIPT"]) | |
2397 else: | 2532 else: |
2398 ms = self.pdata["MAINSCRIPT"] | 2533 ms = self.pdata["MAINSCRIPT"] |
2399 os.makedirs(os.path.dirname(ms), exist_ok=True) | 2534 os.makedirs(os.path.dirname(ms), exist_ok=True) |
2400 with open(ms, "w"): | 2535 with open(ms, "w"): |
2401 pass | 2536 pass |
2402 self.appendFile(ms, True) | 2537 self.appendFile(ms, True) |
2403 | 2538 |
2404 if self.pdata["MAKEPARAMS"]["MakeEnabled"]: | 2539 if self.pdata["MAKEPARAMS"]["MakeEnabled"]: |
2405 mf = self.pdata["MAKEPARAMS"]["MakeFile"] | 2540 mf = self.pdata["MAKEPARAMS"]["MakeFile"] |
2406 if mf: | 2541 if mf: |
2407 if not os.path.isabs(mf): | 2542 if not os.path.isabs(mf): |
2408 mf = os.path.join(self.ppath, mf) | 2543 mf = os.path.join(self.ppath, mf) |
2410 mf = os.path.join(self.ppath, Project.DefaultMakefile) | 2545 mf = os.path.join(self.ppath, Project.DefaultMakefile) |
2411 os.makedirs(os.path.dirname(mf), exist_ok=True) | 2546 os.makedirs(os.path.dirname(mf), exist_ok=True) |
2412 with open(mf, "w"): | 2547 with open(mf, "w"): |
2413 pass | 2548 pass |
2414 self.appendFile(mf) | 2549 self.appendFile(mf) |
2415 | 2550 |
2416 tpd = os.path.join(self.ppath, self.translationsRoot) | 2551 tpd = os.path.join(self.ppath, self.translationsRoot) |
2417 if not self.translationsRoot.endswith(os.sep): | 2552 if not self.translationsRoot.endswith(os.sep): |
2418 tpd = os.path.dirname(tpd) | 2553 tpd = os.path.dirname(tpd) |
2419 if not os.path.isdir(tpd): | 2554 if not os.path.isdir(tpd): |
2420 os.makedirs(tpd, exist_ok=True) | 2555 os.makedirs(tpd, exist_ok=True) |
2421 if self.pdata["TRANSLATIONSBINPATH"]: | 2556 if self.pdata["TRANSLATIONSBINPATH"]: |
2422 tpd = os.path.join( | 2557 tpd = os.path.join(self.ppath, self.pdata["TRANSLATIONSBINPATH"]) |
2423 self.ppath, self.pdata["TRANSLATIONSBINPATH"]) | |
2424 if not os.path.isdir(tpd): | 2558 if not os.path.isdir(tpd): |
2425 os.makedirs(tpd, exist_ok=True) | 2559 os.makedirs(tpd, exist_ok=True) |
2426 | 2560 |
2427 # create management directory if not present | 2561 # create management directory if not present |
2428 self.createProjectManagementDir() | 2562 self.createProjectManagementDir() |
2429 | 2563 |
2430 self.saveProject() | 2564 self.saveProject() |
2431 addAllToVcs = True | 2565 addAllToVcs = True |
2432 else: | 2566 else: |
2433 try: | 2567 try: |
2434 # create management directory if not present | 2568 # create management directory if not present |
2437 EricMessageBox.critical( | 2571 EricMessageBox.critical( |
2438 self.ui, | 2572 self.ui, |
2439 self.tr("Create project management directory"), | 2573 self.tr("Create project management directory"), |
2440 self.tr( | 2574 self.tr( |
2441 "<p>The project directory <b>{0}</b> is not" | 2575 "<p>The project directory <b>{0}</b> is not" |
2442 " writable.</p>") | 2576 " writable.</p>" |
2443 .format(self.ppath)) | 2577 ).format(self.ppath), |
2578 ) | |
2444 return | 2579 return |
2445 | 2580 |
2446 if self.pdata["MAINSCRIPT"]: | 2581 if self.pdata["MAINSCRIPT"]: |
2447 if not os.path.isabs(self.pdata["MAINSCRIPT"]): | 2582 if not os.path.isabs(self.pdata["MAINSCRIPT"]): |
2448 ms = os.path.join( | 2583 ms = os.path.join(self.ppath, self.pdata["MAINSCRIPT"]) |
2449 self.ppath, self.pdata["MAINSCRIPT"]) | |
2450 else: | 2584 else: |
2451 ms = self.pdata["MAINSCRIPT"] | 2585 ms = self.pdata["MAINSCRIPT"] |
2452 if not os.path.exists(ms): | 2586 if not os.path.exists(ms): |
2453 try: | 2587 try: |
2454 os.makedirs(os.path.dirname(ms)) | 2588 os.makedirs(os.path.dirname(ms)) |
2458 EricMessageBox.critical( | 2592 EricMessageBox.critical( |
2459 self.ui, | 2593 self.ui, |
2460 self.tr("Create main script"), | 2594 self.tr("Create main script"), |
2461 self.tr( | 2595 self.tr( |
2462 "<p>The mainscript <b>{0}</b> could not" | 2596 "<p>The mainscript <b>{0}</b> could not" |
2463 " be created.<br/>Reason: {1}</p>") | 2597 " be created.<br/>Reason: {1}</p>" |
2464 .format(ms, str(err))) | 2598 ).format(ms, str(err)), |
2599 ) | |
2465 self.appendFile(ms, True) | 2600 self.appendFile(ms, True) |
2466 else: | 2601 else: |
2467 ms = "" | 2602 ms = "" |
2468 | 2603 |
2469 if self.pdata["MAKEPARAMS"]["MakeEnabled"]: | 2604 if self.pdata["MAKEPARAMS"]["MakeEnabled"]: |
2470 mf = self.pdata["MAKEPARAMS"]["MakeFile"] | 2605 mf = self.pdata["MAKEPARAMS"]["MakeFile"] |
2471 if mf: | 2606 if mf: |
2472 if not os.path.isabs(mf): | 2607 if not os.path.isabs(mf): |
2473 mf = os.path.join(self.ppath, mf) | 2608 mf = os.path.join(self.ppath, mf) |
2482 EricMessageBox.critical( | 2617 EricMessageBox.critical( |
2483 self.ui, | 2618 self.ui, |
2484 self.tr("Create Makefile"), | 2619 self.tr("Create Makefile"), |
2485 self.tr( | 2620 self.tr( |
2486 "<p>The makefile <b>{0}</b> could not" | 2621 "<p>The makefile <b>{0}</b> could not" |
2487 " be created.<br/>Reason: {1}</p>") | 2622 " be created.<br/>Reason: {1}</p>" |
2488 .format(mf, str(err))) | 2623 ).format(mf, str(err)), |
2624 ) | |
2489 self.appendFile(mf) | 2625 self.appendFile(mf) |
2490 | 2626 |
2491 # add existing files to the project | 2627 # add existing files to the project |
2492 res = EricMessageBox.yesNo( | 2628 res = EricMessageBox.yesNo( |
2493 self.ui, | 2629 self.ui, |
2494 self.tr("New Project"), | 2630 self.tr("New Project"), |
2495 self.tr("""Add existing files to the project?"""), | 2631 self.tr("""Add existing files to the project?"""), |
2496 yesDefault=True) | 2632 yesDefault=True, |
2633 ) | |
2497 if res: | 2634 if res: |
2498 self.newProjectAddFiles(ms) | 2635 self.newProjectAddFiles(ms) |
2499 addAllToVcs = res | 2636 addAllToVcs = res |
2500 # create an empty __init__.py file to make it a Python package | 2637 # create an empty __init__.py file to make it a Python package |
2501 # if none exists (only for Python and Python3) | 2638 # if none exists (only for Python and Python3) |
2502 if self.pdata["PROGLANGUAGE"] in [ | 2639 if self.pdata["PROGLANGUAGE"] in ["Python3", "MicroPython"]: |
2503 "Python3", "MicroPython" | |
2504 ]: | |
2505 fn = os.path.join(self.ppath, "__init__.py") | 2640 fn = os.path.join(self.ppath, "__init__.py") |
2506 if not os.path.exists(fn): | 2641 if not os.path.exists(fn): |
2507 with open(fn, "w", encoding="utf-8"): | 2642 with open(fn, "w", encoding="utf-8"): |
2508 pass | 2643 pass |
2509 self.appendFile(fn, True) | 2644 self.appendFile(fn, True) |
2510 self.saveProject() | 2645 self.saveProject() |
2511 | 2646 |
2512 # check, if the existing project directory is already under | 2647 # check, if the existing project directory is already under |
2513 # VCS control | 2648 # VCS control |
2514 pluginManager = ericApp().getObject("PluginManager") | 2649 pluginManager = ericApp().getObject("PluginManager") |
2515 for indicator, vcsData in list( | 2650 for indicator, vcsData in list( |
2516 pluginManager.getVcsSystemIndicators().items()): | 2651 pluginManager.getVcsSystemIndicators().items() |
2652 ): | |
2517 if os.path.exists(os.path.join(self.ppath, indicator)): | 2653 if os.path.exists(os.path.join(self.ppath, indicator)): |
2518 if len(vcsData) > 1: | 2654 if len(vcsData) > 1: |
2519 vcsList = [] | 2655 vcsList = [] |
2520 for _vcsSystemStr, vcsSystemDisplay in vcsData: | 2656 for _vcsSystemStr, vcsSystemDisplay in vcsData: |
2521 vcsList.append(vcsSystemDisplay) | 2657 vcsList.append(vcsSystemDisplay) |
2522 res, vcs_ok = QInputDialog.getItem( | 2658 res, vcs_ok = QInputDialog.getItem( |
2523 None, | 2659 None, |
2524 self.tr("New Project"), | 2660 self.tr("New Project"), |
2525 self.tr("Select Version Control System"), | 2661 self.tr("Select Version Control System"), |
2526 vcsList, | 2662 vcsList, |
2527 0, False) | 2663 0, |
2664 False, | |
2665 ) | |
2528 if vcs_ok: | 2666 if vcs_ok: |
2529 for vcsSystemStr, vcsSystemDisplay in vcsData: | 2667 for vcsSystemStr, vcsSystemDisplay in vcsData: |
2530 if res == vcsSystemDisplay: | 2668 if res == vcsSystemDisplay: |
2531 vcsSystem = vcsSystemStr | 2669 vcsSystem = vcsSystemStr |
2532 break | 2670 break |
2545 vcores = EricMessageBox.yesNo( | 2683 vcores = EricMessageBox.yesNo( |
2546 self.ui, | 2684 self.ui, |
2547 self.tr("New Project"), | 2685 self.tr("New Project"), |
2548 self.tr( | 2686 self.tr( |
2549 """Would you like to edit the VCS""" | 2687 """Would you like to edit the VCS""" |
2550 """ command options?""")) | 2688 """ command options?""" |
2689 ), | |
2690 ) | |
2551 else: | 2691 else: |
2552 vcores = False | 2692 vcores = False |
2553 if vcores: | 2693 if vcores: |
2554 from VCS.CommandOptionsDialog import ( | 2694 from VCS.CommandOptionsDialog import ( |
2555 VcsCommandOptionsDialog | 2695 VcsCommandOptionsDialog, |
2556 ) | 2696 ) |
2697 | |
2557 codlg = VcsCommandOptionsDialog(self.vcs) | 2698 codlg = VcsCommandOptionsDialog(self.vcs) |
2558 if codlg.exec() == QDialog.DialogCode.Accepted: | 2699 if codlg.exec() == QDialog.DialogCode.Accepted: |
2559 self.vcs.vcsSetOptions(codlg.getOptions()) | 2700 self.vcs.vcsSetOptions(codlg.getOptions()) |
2560 # add project file to repository | 2701 # add project file to repository |
2561 if res == 0: | 2702 if res == 0: |
2562 apres = EricMessageBox.yesNo( | 2703 apres = EricMessageBox.yesNo( |
2563 self.ui, | 2704 self.ui, |
2564 self.tr("New project"), | 2705 self.tr("New project"), |
2565 self.tr( | 2706 self.tr( |
2566 "Shall the project file be added" | 2707 "Shall the project file be added" |
2567 " to the repository?"), | 2708 " to the repository?" |
2568 yesDefault=True) | 2709 ), |
2710 yesDefault=True, | |
2711 ) | |
2569 if apres: | 2712 if apres: |
2570 self.saveProject() | 2713 self.saveProject() |
2571 self.vcs.vcsAdd(self.pfile) | 2714 self.vcs.vcsAdd(self.pfile) |
2572 else: | 2715 else: |
2573 self.pdata["VCS"] = 'None' | 2716 self.pdata["VCS"] = "None" |
2574 self.saveProject() | 2717 self.saveProject() |
2575 break | 2718 break |
2576 | 2719 |
2577 # put the project under VCS control | 2720 # put the project under VCS control |
2578 if ( | 2721 if self.vcs is None and self.vcsSoftwareAvailable() and self.vcsRequested: |
2579 self.vcs is None and | |
2580 self.vcsSoftwareAvailable() and | |
2581 self.vcsRequested | |
2582 ): | |
2583 vcsSystemsDict = ( | 2722 vcsSystemsDict = ( |
2584 ericApp().getObject("PluginManager") | 2723 ericApp() |
2724 .getObject("PluginManager") | |
2585 .getPluginDisplayStrings("version_control") | 2725 .getPluginDisplayStrings("version_control") |
2586 ) | 2726 ) |
2587 vcsSystemsDisplay = [self.tr("None")] | 2727 vcsSystemsDisplay = [self.tr("None")] |
2588 keys = sorted(vcsSystemsDict.keys()) | 2728 keys = sorted(vcsSystemsDict.keys()) |
2589 for key in keys: | 2729 for key in keys: |
2590 vcsSystemsDisplay.append(vcsSystemsDict[key]) | 2730 vcsSystemsDisplay.append(vcsSystemsDict[key]) |
2591 vcsSelected, ok = QInputDialog.getItem( | 2731 vcsSelected, ok = QInputDialog.getItem( |
2592 None, | 2732 None, |
2593 self.tr("New Project"), | 2733 self.tr("New Project"), |
2594 self.tr( | 2734 self.tr("Select version control system for the project"), |
2595 "Select version control system for the project"), | |
2596 vcsSystemsDisplay, | 2735 vcsSystemsDisplay, |
2597 0, False) | 2736 0, |
2737 False, | |
2738 ) | |
2598 if ok and vcsSelected != self.tr("None"): | 2739 if ok and vcsSelected != self.tr("None"): |
2599 for vcsSystem, vcsSystemDisplay in vcsSystemsDict.items(): | 2740 for vcsSystem, vcsSystemDisplay in vcsSystemsDict.items(): |
2600 if vcsSystemDisplay == vcsSelected: | 2741 if vcsSystemDisplay == vcsSelected: |
2601 self.pdata["VCS"] = vcsSystem | 2742 self.pdata["VCS"] = vcsSystem |
2602 break | 2743 break |
2603 else: | 2744 else: |
2604 self.pdata["VCS"] = 'None' | 2745 self.pdata["VCS"] = "None" |
2605 else: | 2746 else: |
2606 self.pdata["VCS"] = 'None' | 2747 self.pdata["VCS"] = "None" |
2607 self.vcs = self.initVCS() | 2748 self.vcs = self.initVCS() |
2608 if self.vcs is not None: | 2749 if self.vcs is not None: |
2609 vcsdlg = self.vcs.vcsOptionsDialog(self, self.name) | 2750 vcsdlg = self.vcs.vcsOptionsDialog(self, self.name) |
2610 if vcsdlg.exec() == QDialog.DialogCode.Accepted: | 2751 if vcsdlg.exec() == QDialog.DialogCode.Accepted: |
2611 vcsDataDict = vcsdlg.getData() | 2752 vcsDataDict = vcsdlg.getData() |
2612 else: | 2753 else: |
2613 self.pdata["VCS"] = 'None' | 2754 self.pdata["VCS"] = "None" |
2614 self.vcs = self.initVCS() | 2755 self.vcs = self.initVCS() |
2615 self.setDirty(True) | 2756 self.setDirty(True) |
2616 if self.vcs is not None: | 2757 if self.vcs is not None: |
2617 # edit VCS command options | 2758 # edit VCS command options |
2618 if self.vcs.vcsSupportCommandOptions(): | 2759 if self.vcs.vcsSupportCommandOptions(): |
2619 vcores = EricMessageBox.yesNo( | 2760 vcores = EricMessageBox.yesNo( |
2620 self.ui, | 2761 self.ui, |
2621 self.tr("New Project"), | 2762 self.tr("New Project"), |
2622 self.tr( | 2763 self.tr( |
2623 """Would you like to edit the VCS command""" | 2764 """Would you like to edit the VCS command""" |
2624 """ options?""")) | 2765 """ options?""" |
2766 ), | |
2767 ) | |
2625 else: | 2768 else: |
2626 vcores = False | 2769 vcores = False |
2627 if vcores: | 2770 if vcores: |
2628 from VCS.CommandOptionsDialog import ( | 2771 from VCS.CommandOptionsDialog import VcsCommandOptionsDialog |
2629 VcsCommandOptionsDialog | 2772 |
2630 ) | |
2631 codlg = VcsCommandOptionsDialog(self.vcs) | 2773 codlg = VcsCommandOptionsDialog(self.vcs) |
2632 if codlg.exec() == QDialog.DialogCode.Accepted: | 2774 if codlg.exec() == QDialog.DialogCode.Accepted: |
2633 self.vcs.vcsSetOptions(codlg.getOptions()) | 2775 self.vcs.vcsSetOptions(codlg.getOptions()) |
2634 | 2776 |
2635 # create the project in the VCS | 2777 # create the project in the VCS |
2636 self.vcs.vcsSetDataFromDict(vcsDataDict) | 2778 self.vcs.vcsSetDataFromDict(vcsDataDict) |
2637 self.saveProject() | 2779 self.saveProject() |
2638 self.vcs.vcsConvertProject(vcsDataDict, self, | 2780 self.vcs.vcsConvertProject(vcsDataDict, self, addAll=addAllToVcs) |
2639 addAll=addAllToVcs) | |
2640 else: | 2781 else: |
2641 self.newProjectHooks.emit() | 2782 self.newProjectHooks.emit() |
2642 self.newProject.emit() | 2783 self.newProject.emit() |
2643 | 2784 |
2644 else: | 2785 else: |
2645 self.newProjectHooks.emit() | 2786 self.newProjectHooks.emit() |
2646 self.newProject.emit() | 2787 self.newProject.emit() |
2647 | 2788 |
2648 def newProjectAddFiles(self, mainscript): | 2789 def newProjectAddFiles(self, mainscript): |
2649 """ | 2790 """ |
2650 Public method to add files to a new project. | 2791 Public method to add files to a new project. |
2651 | 2792 |
2652 @param mainscript name of the mainscript (string) | 2793 @param mainscript name of the mainscript (string) |
2653 """ | 2794 """ |
2654 # Show the file type associations for the user to change | 2795 # Show the file type associations for the user to change |
2655 self.__showFiletypeAssociations() | 2796 self.__showFiletypeAssociations() |
2656 | 2797 |
2657 with EricOverrideCursor(): | 2798 with EricOverrideCursor(): |
2658 # search the project directory for files with known extensions | 2799 # search the project directory for files with known extensions |
2659 filespecs = list(self.pdata["FILETYPES"].keys()) | 2800 filespecs = list(self.pdata["FILETYPES"].keys()) |
2660 for filespec in filespecs: | 2801 for filespec in filespecs: |
2661 files = Utilities.direntries(self.ppath, True, filespec) | 2802 files = Utilities.direntries(self.ppath, True, filespec) |
2662 for file in files: | 2803 for file in files: |
2663 self.appendFile(file) | 2804 self.appendFile(file) |
2664 | 2805 |
2665 # special handling for translation files | 2806 # special handling for translation files |
2666 if self.translationsRoot: | 2807 if self.translationsRoot: |
2667 tpd = os.path.join(self.ppath, self.translationsRoot) | 2808 tpd = os.path.join(self.ppath, self.translationsRoot) |
2668 if not self.translationsRoot.endswith(os.sep): | 2809 if not self.translationsRoot.endswith(os.sep): |
2669 tpd = os.path.dirname(tpd) | 2810 tpd = os.path.dirname(tpd) |
2673 if self.pdata["TRANSLATIONPATTERN"]: | 2814 if self.pdata["TRANSLATIONPATTERN"]: |
2674 pattern = os.path.basename(self.pdata["TRANSLATIONPATTERN"]) | 2815 pattern = os.path.basename(self.pdata["TRANSLATIONPATTERN"]) |
2675 if "%language%" in pattern: | 2816 if "%language%" in pattern: |
2676 pattern = pattern.replace("%language%", "*") | 2817 pattern = pattern.replace("%language%", "*") |
2677 else: | 2818 else: |
2678 tpd = self.pdata["TRANSLATIONPATTERN"].split( | 2819 tpd = self.pdata["TRANSLATIONPATTERN"].split("%language%")[0] |
2679 "%language%")[0] | |
2680 else: | 2820 else: |
2681 pattern = "*.ts" | 2821 pattern = "*.ts" |
2682 tslist.extend(Utilities.direntries(tpd, True, pattern)) | 2822 tslist.extend(Utilities.direntries(tpd, True, pattern)) |
2683 pattern = self.__binaryTranslationFile(pattern) | 2823 pattern = self.__binaryTranslationFile(pattern) |
2684 if pattern: | 2824 if pattern: |
2685 tslist.extend(Utilities.direntries(tpd, True, pattern)) | 2825 tslist.extend(Utilities.direntries(tpd, True, pattern)) |
2686 if tslist: | 2826 if tslist: |
2687 if '_' in os.path.basename(tslist[0]): | 2827 if "_" in os.path.basename(tslist[0]): |
2688 # the first entry determines the mainscript name | 2828 # the first entry determines the mainscript name |
2689 mainscriptname = ( | 2829 mainscriptname = ( |
2690 os.path.splitext(mainscript)[0] or | 2830 os.path.splitext(mainscript)[0] |
2691 os.path.basename(tslist[0]).split('_')[0] | 2831 or os.path.basename(tslist[0]).split("_")[0] |
2692 ) | 2832 ) |
2693 self.pdata["TRANSLATIONPATTERN"] = os.path.join( | 2833 self.pdata["TRANSLATIONPATTERN"] = os.path.join( |
2694 os.path.dirname(tslist[0]), | 2834 os.path.dirname(tslist[0]), |
2695 "{0}_%language%{1}".format( | 2835 "{0}_%language%{1}".format( |
2696 os.path.basename(tslist[0]).split('_')[0], | 2836 os.path.basename(tslist[0]).split("_")[0], |
2697 os.path.splitext(tslist[0])[1])) | 2837 os.path.splitext(tslist[0])[1], |
2838 ), | |
2839 ) | |
2698 else: | 2840 else: |
2699 mainscriptname = "" | 2841 mainscriptname = "" |
2700 pattern, ok = QInputDialog.getText( | 2842 pattern, ok = QInputDialog.getText( |
2701 None, | 2843 None, |
2702 self.tr("Translation Pattern"), | 2844 self.tr("Translation Pattern"), |
2703 self.tr( | 2845 self.tr( |
2704 "Enter the path pattern for translation files " | 2846 "Enter the path pattern for translation files " |
2705 "(use '%language%' in place of the language" | 2847 "(use '%language%' in place of the language" |
2706 " code):"), | 2848 " code):" |
2849 ), | |
2707 QLineEdit.EchoMode.Normal, | 2850 QLineEdit.EchoMode.Normal, |
2708 tslist[0]) | 2851 tslist[0], |
2852 ) | |
2709 if pattern: | 2853 if pattern: |
2710 self.pdata["TRANSLATIONPATTERN"] = pattern | 2854 self.pdata["TRANSLATIONPATTERN"] = pattern |
2711 if self.pdata["TRANSLATIONPATTERN"]: | 2855 if self.pdata["TRANSLATIONPATTERN"]: |
2712 self.pdata["TRANSLATIONPATTERN"] = self.getRelativePath( | 2856 self.pdata["TRANSLATIONPATTERN"] = self.getRelativePath( |
2713 self.pdata["TRANSLATIONPATTERN"]) | 2857 self.pdata["TRANSLATIONPATTERN"] |
2858 ) | |
2714 pattern = self.pdata["TRANSLATIONPATTERN"].replace( | 2859 pattern = self.pdata["TRANSLATIONPATTERN"].replace( |
2715 "%language%", "*") | 2860 "%language%", "*" |
2861 ) | |
2716 for ts in tslist: | 2862 for ts in tslist: |
2717 if fnmatch.fnmatch(ts, pattern): | 2863 if fnmatch.fnmatch(ts, pattern): |
2718 self.pdata["TRANSLATIONS"].append(ts) | 2864 self.pdata["TRANSLATIONS"].append(ts) |
2719 self.projectLanguageAdded.emit(ts) | 2865 self.projectLanguageAdded.emit(ts) |
2720 if self.pdata["TRANSLATIONSBINPATH"]: | 2866 if self.pdata["TRANSLATIONSBINPATH"]: |
2721 tpd = os.path.join(self.ppath, | 2867 tpd = os.path.join( |
2722 self.pdata["TRANSLATIONSBINPATH"]) | 2868 self.ppath, self.pdata["TRANSLATIONSBINPATH"] |
2869 ) | |
2723 pattern = os.path.basename( | 2870 pattern = os.path.basename( |
2724 self.pdata["TRANSLATIONPATTERN"]).replace( | 2871 self.pdata["TRANSLATIONPATTERN"] |
2725 "%language%", "*") | 2872 ).replace("%language%", "*") |
2726 pattern = self.__binaryTranslationFile(pattern) | 2873 pattern = self.__binaryTranslationFile(pattern) |
2727 qmlist = Utilities.direntries(tpd, True, pattern) | 2874 qmlist = Utilities.direntries(tpd, True, pattern) |
2728 for qm in qmlist: | 2875 for qm in qmlist: |
2729 self.pdata["TRANSLATIONS"].append(qm) | 2876 self.pdata["TRANSLATIONS"].append(qm) |
2730 self.projectLanguageAdded.emit(qm) | 2877 self.projectLanguageAdded.emit(qm) |
2731 if not self.pdata["MAINSCRIPT"] and bool(mainscriptname): | 2878 if not self.pdata["MAINSCRIPT"] and bool(mainscriptname): |
2732 if self.pdata["PROGLANGUAGE"] in [ | 2879 if self.pdata["PROGLANGUAGE"] in ["Python3", "MicroPython"]: |
2733 "Python3", "MicroPython" | 2880 self.pdata["MAINSCRIPT"] = "{0}.py".format(mainscriptname) |
2734 ]: | |
2735 self.pdata["MAINSCRIPT"] = '{0}.py'.format( | |
2736 mainscriptname) | |
2737 elif self.pdata["PROGLANGUAGE"] == "Ruby": | 2881 elif self.pdata["PROGLANGUAGE"] == "Ruby": |
2738 self.pdata["MAINSCRIPT"] = '{0}.rb'.format( | 2882 self.pdata["MAINSCRIPT"] = "{0}.rb".format(mainscriptname) |
2739 mainscriptname) | |
2740 self.setDirty(True) | 2883 self.setDirty(True) |
2741 | 2884 |
2742 def __showProperties(self): | 2885 def __showProperties(self): |
2743 """ | 2886 """ |
2744 Private slot to display the properties dialog. | 2887 Private slot to display the properties dialog. |
2745 """ | 2888 """ |
2746 from .PropertiesDialog import PropertiesDialog | 2889 from .PropertiesDialog import PropertiesDialog |
2890 | |
2747 dlg = PropertiesDialog(self, False) | 2891 dlg = PropertiesDialog(self, False) |
2748 if dlg.exec() == QDialog.DialogCode.Accepted: | 2892 if dlg.exec() == QDialog.DialogCode.Accepted: |
2749 projectType = self.pdata["PROJECTTYPE"] | 2893 projectType = self.pdata["PROJECTTYPE"] |
2750 dlg.storeData() | 2894 dlg.storeData() |
2751 self.setDirty(True) | 2895 self.setDirty(True) |
2752 if self.pdata["MAINSCRIPT"]: | 2896 if self.pdata["MAINSCRIPT"]: |
2753 if not os.path.isabs(self.pdata["MAINSCRIPT"]): | 2897 if not os.path.isabs(self.pdata["MAINSCRIPT"]): |
2754 ms = os.path.join( | 2898 ms = os.path.join(self.ppath, self.pdata["MAINSCRIPT"]) |
2755 self.ppath, self.pdata["MAINSCRIPT"]) | |
2756 else: | 2899 else: |
2757 ms = self.pdata["MAINSCRIPT"] | 2900 ms = self.pdata["MAINSCRIPT"] |
2758 if os.path.exists(ms): | 2901 if os.path.exists(ms): |
2759 self.appendFile(ms) | 2902 self.appendFile(ms) |
2760 | 2903 |
2761 if self.pdata["MAKEPARAMS"]["MakeEnabled"]: | 2904 if self.pdata["MAKEPARAMS"]["MakeEnabled"]: |
2762 mf = self.pdata["MAKEPARAMS"]["MakeFile"] | 2905 mf = self.pdata["MAKEPARAMS"]["MakeFile"] |
2763 if mf: | 2906 if mf: |
2764 if not os.path.isabs(mf): | 2907 if not os.path.isabs(mf): |
2765 mf = os.path.join(self.ppath, mf) | 2908 mf = os.path.join(self.ppath, mf) |
2773 EricMessageBox.critical( | 2916 EricMessageBox.critical( |
2774 self.ui, | 2917 self.ui, |
2775 self.tr("Create Makefile"), | 2918 self.tr("Create Makefile"), |
2776 self.tr( | 2919 self.tr( |
2777 "<p>The makefile <b>{0}</b> could not" | 2920 "<p>The makefile <b>{0}</b> could not" |
2778 " be created.<br/>Reason: {1}</p>") | 2921 " be created.<br/>Reason: {1}</p>" |
2779 .format(mf, str(err))) | 2922 ).format(mf, str(err)), |
2923 ) | |
2780 self.appendFile(mf) | 2924 self.appendFile(mf) |
2781 | 2925 |
2782 if self.pdata["PROJECTTYPE"] != projectType: | 2926 if self.pdata["PROJECTTYPE"] != projectType: |
2783 # reinitialize filetype associations | 2927 # reinitialize filetype associations |
2784 self.initFileTypes() | 2928 self.initFileTypes() |
2785 | 2929 |
2786 if self.translationsRoot: | 2930 if self.translationsRoot: |
2787 tp = os.path.join(self.ppath, self.translationsRoot) | 2931 tp = os.path.join(self.ppath, self.translationsRoot) |
2788 if not self.translationsRoot.endswith(os.sep): | 2932 if not self.translationsRoot.endswith(os.sep): |
2789 tp = os.path.dirname(tp) | 2933 tp = os.path.dirname(tp) |
2790 else: | 2934 else: |
2791 tp = self.ppath | 2935 tp = self.ppath |
2792 if not os.path.isdir(tp): | 2936 if not os.path.isdir(tp): |
2793 os.makedirs(tp) | 2937 os.makedirs(tp) |
2794 if tp != self.ppath and tp not in self.subdirs: | 2938 if tp != self.ppath and tp not in self.subdirs: |
2795 self.subdirs.append(tp) | 2939 self.subdirs.append(tp) |
2796 | 2940 |
2797 if self.pdata["TRANSLATIONSBINPATH"]: | 2941 if self.pdata["TRANSLATIONSBINPATH"]: |
2798 tp = os.path.join( | 2942 tp = os.path.join(self.ppath, self.pdata["TRANSLATIONSBINPATH"]) |
2799 self.ppath, self.pdata["TRANSLATIONSBINPATH"]) | |
2800 if not os.path.isdir(tp): | 2943 if not os.path.isdir(tp): |
2801 os.makedirs(tp) | 2944 os.makedirs(tp) |
2802 if tp != self.ppath and tp not in self.subdirs: | 2945 if tp != self.ppath and tp not in self.subdirs: |
2803 self.subdirs.append(tp) | 2946 self.subdirs.append(tp) |
2804 | 2947 |
2805 self.pluginGrp.setEnabled( | 2948 self.pluginGrp.setEnabled(self.pdata["PROJECTTYPE"] in ["E7Plugin"]) |
2806 self.pdata["PROJECTTYPE"] in ["E7Plugin"]) | 2949 |
2807 | |
2808 self.__model.projectPropertiesChanged() | 2950 self.__model.projectPropertiesChanged() |
2809 self.projectPropertiesChanged.emit() | 2951 self.projectPropertiesChanged.emit() |
2810 | 2952 |
2811 if self.pdata["PROJECTTYPE"] != projectType: | 2953 if self.pdata["PROJECTTYPE"] != projectType: |
2812 self.__reorganizeFiles() | 2954 self.__reorganizeFiles() |
2813 | 2955 |
2814 def __showUserProperties(self): | 2956 def __showUserProperties(self): |
2815 """ | 2957 """ |
2816 Private slot to display the user specific properties dialog. | 2958 Private slot to display the user specific properties dialog. |
2817 """ | 2959 """ |
2818 vcsSystem = self.pdata["VCS"] or None | 2960 vcsSystem = self.pdata["VCS"] or None |
2819 vcsSystemOverride = self.pudata["VCSOVERRIDE"] or None | 2961 vcsSystemOverride = self.pudata["VCSOVERRIDE"] or None |
2820 | 2962 |
2821 from .UserPropertiesDialog import UserPropertiesDialog | 2963 from .UserPropertiesDialog import UserPropertiesDialog |
2964 | |
2822 dlg = UserPropertiesDialog(self) | 2965 dlg = UserPropertiesDialog(self) |
2823 if dlg.exec() == QDialog.DialogCode.Accepted: | 2966 if dlg.exec() == QDialog.DialogCode.Accepted: |
2824 dlg.storeData() | 2967 dlg.storeData() |
2825 | 2968 |
2826 if ( | 2969 if ( |
2827 (self.pdata["VCS"] and | 2970 (self.pdata["VCS"] and self.pdata["VCS"] != vcsSystem) |
2828 self.pdata["VCS"] != vcsSystem) or | 2971 or ( |
2829 (self.pudata["VCSOVERRIDE"] and | 2972 self.pudata["VCSOVERRIDE"] |
2830 self.pudata["VCSOVERRIDE"] != vcsSystemOverride) or | 2973 and self.pudata["VCSOVERRIDE"] != vcsSystemOverride |
2831 (vcsSystemOverride is not None and | 2974 ) |
2832 not self.pudata["VCSOVERRIDE"]) | 2975 or (vcsSystemOverride is not None and not self.pudata["VCSOVERRIDE"]) |
2833 ): | 2976 ): |
2834 # stop the VCS monitor thread and shutdown VCS | 2977 # stop the VCS monitor thread and shutdown VCS |
2835 if self.vcs is not None: | 2978 if self.vcs is not None: |
2836 self.vcs.stopStatusMonitor() | 2979 self.vcs.stopStatusMonitor() |
2837 self.vcs.vcsShutdown() | 2980 self.vcs.vcsShutdown() |
2841 # reinit VCS | 2984 # reinit VCS |
2842 self.vcs = self.initVCS() | 2985 self.vcs = self.initVCS() |
2843 # start the VCS monitor thread | 2986 # start the VCS monitor thread |
2844 self.__vcsConnectStatusMonitor() | 2987 self.__vcsConnectStatusMonitor() |
2845 self.reinitVCS.emit() | 2988 self.reinitVCS.emit() |
2846 | 2989 |
2847 if self.pudata["VCSSTATUSMONITORINTERVAL"]: | 2990 if self.pudata["VCSSTATUSMONITORINTERVAL"]: |
2848 self.setStatusMonitorInterval( | 2991 self.setStatusMonitorInterval(self.pudata["VCSSTATUSMONITORINTERVAL"]) |
2849 self.pudata["VCSSTATUSMONITORINTERVAL"]) | |
2850 else: | 2992 else: |
2851 self.setStatusMonitorInterval( | 2993 self.setStatusMonitorInterval( |
2852 Preferences.getVCS("StatusMonitorInterval")) | 2994 Preferences.getVCS("StatusMonitorInterval") |
2853 | 2995 ) |
2996 | |
2854 def __showFiletypeAssociations(self): | 2997 def __showFiletypeAssociations(self): |
2855 """ | 2998 """ |
2856 Private slot to display the filetype association dialog. | 2999 Private slot to display the filetype association dialog. |
2857 """ | 3000 """ |
2858 from .FiletypeAssociationDialog import FiletypeAssociationDialog | 3001 from .FiletypeAssociationDialog import FiletypeAssociationDialog |
3002 | |
2859 dlg = FiletypeAssociationDialog(self) | 3003 dlg = FiletypeAssociationDialog(self) |
2860 if dlg.exec() == QDialog.DialogCode.Accepted: | 3004 if dlg.exec() == QDialog.DialogCode.Accepted: |
2861 dlg.transferData() | 3005 dlg.transferData() |
2862 self.setDirty(True) | 3006 self.setDirty(True) |
2863 self.__reorganizeFiles() | 3007 self.__reorganizeFiles() |
2864 | 3008 |
2865 def getFiletypeAssociations(self, associationType): | 3009 def getFiletypeAssociations(self, associationType): |
2866 """ | 3010 """ |
2867 Public method to get the list of file type associations for | 3011 Public method to get the list of file type associations for |
2868 the given association type. | 3012 the given association type. |
2869 | 3013 |
2870 @param associationType type of the association (one of FORMS, | 3014 @param associationType type of the association (one of FORMS, |
2871 INTERFACES, OTHERS, PROTOCOLS, RESOURCES, SOURCES, | 3015 INTERFACES, OTHERS, PROTOCOLS, RESOURCES, SOURCES, |
2872 TRANSLATIONS or __IGNORE__) | 3016 TRANSLATIONS or __IGNORE__) |
2873 @type str | 3017 @type str |
2874 @return list of file patterns for the given type | 3018 @return list of file patterns for the given type |
2875 @rtype list of str | 3019 @rtype list of str |
2876 """ | 3020 """ |
2877 return [assoc for assoc in self.pdata["FILETYPES"] | 3021 return [ |
2878 if self.pdata["FILETYPES"][assoc] == associationType] | 3022 assoc |
2879 | 3023 for assoc in self.pdata["FILETYPES"] |
3024 if self.pdata["FILETYPES"][assoc] == associationType | |
3025 ] | |
3026 | |
2880 def __showLexerAssociations(self): | 3027 def __showLexerAssociations(self): |
2881 """ | 3028 """ |
2882 Private slot to display the lexer association dialog. | 3029 Private slot to display the lexer association dialog. |
2883 """ | 3030 """ |
2884 from .LexerAssociationDialog import LexerAssociationDialog | 3031 from .LexerAssociationDialog import LexerAssociationDialog |
3032 | |
2885 dlg = LexerAssociationDialog(self) | 3033 dlg = LexerAssociationDialog(self) |
2886 if dlg.exec() == QDialog.DialogCode.Accepted: | 3034 if dlg.exec() == QDialog.DialogCode.Accepted: |
2887 dlg.transferData() | 3035 dlg.transferData() |
2888 self.setDirty(True) | 3036 self.setDirty(True) |
2889 self.lexerAssociationsChanged.emit() | 3037 self.lexerAssociationsChanged.emit() |
2890 | 3038 |
2891 def getEditorLexerAssoc(self, filename): | 3039 def getEditorLexerAssoc(self, filename): |
2892 """ | 3040 """ |
2893 Public method to retrieve a lexer association. | 3041 Public method to retrieve a lexer association. |
2894 | 3042 |
2895 @param filename filename used to determine the associated lexer | 3043 @param filename filename used to determine the associated lexer |
2896 language (string) | 3044 language (string) |
2897 @return the requested lexer language (string) | 3045 @return the requested lexer language (string) |
2898 """ | 3046 """ |
2899 # try user settings first | 3047 # try user settings first |
2900 for pattern, language in list(self.pdata["LEXERASSOCS"].items()): | 3048 for pattern, language in list(self.pdata["LEXERASSOCS"].items()): |
2901 if fnmatch.fnmatch(filename, pattern): | 3049 if fnmatch.fnmatch(filename, pattern): |
2902 return language | 3050 return language |
2903 | 3051 |
2904 # try project type specific defaults next | 3052 # try project type specific defaults next |
2905 projectType = self.pdata["PROJECTTYPE"] | 3053 projectType = self.pdata["PROJECTTYPE"] |
2906 with contextlib.suppress(KeyError): | 3054 with contextlib.suppress(KeyError): |
2907 if self.__lexerAssociationCallbacks[projectType] is not None: | 3055 if self.__lexerAssociationCallbacks[projectType] is not None: |
2908 return self.__lexerAssociationCallbacks[projectType](filename) | 3056 return self.__lexerAssociationCallbacks[projectType](filename) |
2909 | 3057 |
2910 # return empty string to signal to use the global setting | 3058 # return empty string to signal to use the global setting |
2911 return "" | 3059 return "" |
2912 | 3060 |
2913 def getIgnorePatterns(self): | 3061 def getIgnorePatterns(self): |
2914 """ | 3062 """ |
2915 Public method to get the list of file name patterns for files to be | 3063 Public method to get the list of file name patterns for files to be |
2916 ignored. | 3064 ignored. |
2917 | 3065 |
2918 @return list of ignore file name patterns | 3066 @return list of ignore file name patterns |
2919 @rtype list of str | 3067 @rtype list of str |
2920 """ | 3068 """ |
2921 return self.getFiletypeAssociations("__IGNORE__") | 3069 return self.getFiletypeAssociations("__IGNORE__") |
2922 | 3070 |
2923 @pyqtSlot() | 3071 @pyqtSlot() |
2924 @pyqtSlot(str) | 3072 @pyqtSlot(str) |
2925 def openProject(self, fn=None, restoreSession=True, reopen=False): | 3073 def openProject(self, fn=None, restoreSession=True, reopen=False): |
2926 """ | 3074 """ |
2927 Public slot to open a project. | 3075 Public slot to open a project. |
2928 | 3076 |
2929 @param fn optional filename of the project file to be read | 3077 @param fn optional filename of the project file to be read |
2930 @param restoreSession flag indicating to restore the project | 3078 @param restoreSession flag indicating to restore the project |
2931 session (boolean) | 3079 session (boolean) |
2932 @param reopen flag indicating a reopening of the project (boolean) | 3080 @param reopen flag indicating a reopening of the project (boolean) |
2933 """ | 3081 """ |
2934 if not self.checkDirty(): | 3082 if not self.checkDirty(): |
2935 return | 3083 return |
2936 | 3084 |
2937 if fn is None: | 3085 if fn is None: |
2938 fn = EricFileDialog.getOpenFileName( | 3086 fn = EricFileDialog.getOpenFileName( |
2939 self.parent(), | 3087 self.parent(), |
2940 self.tr("Open project"), | 3088 self.tr("Open project"), |
2941 Preferences.getMultiProject("Workspace") or | 3089 Preferences.getMultiProject("Workspace") or Utilities.getHomeDir(), |
2942 Utilities.getHomeDir(), | 3090 self.tr("Project Files (*.epj);;XML Project Files (*.e4p)"), |
2943 self.tr("Project Files (*.epj);;XML Project Files (*.e4p)")) | 3091 ) |
2944 | 3092 |
2945 if fn and self.closeProject(): | 3093 if fn and self.closeProject(): |
2946 with EricOverrideCursor(): | 3094 with EricOverrideCursor(): |
2947 ok = self.__readProject(fn) | 3095 ok = self.__readProject(fn) |
2948 if ok: | 3096 if ok: |
2949 self.opened = True | 3097 self.opened = True |
2950 if not self.pdata["FILETYPES"]: | 3098 if not self.pdata["FILETYPES"]: |
2951 self.initFileTypes() | 3099 self.initFileTypes() |
2952 else: | 3100 else: |
2953 self.updateFileTypes() | 3101 self.updateFileTypes() |
2954 | 3102 |
2955 try: | 3103 try: |
2956 # create management directory if not present | 3104 # create management directory if not present |
2957 self.createProjectManagementDir() | 3105 self.createProjectManagementDir() |
2958 except OSError: | 3106 except OSError: |
2959 EricMessageBox.critical( | 3107 EricMessageBox.critical( |
2960 self.ui, | 3108 self.ui, |
2961 self.tr("Create project management directory"), | 3109 self.tr("Create project management directory"), |
2962 self.tr( | 3110 self.tr( |
2963 "<p>The project directory <b>{0}</b> is not" | 3111 "<p>The project directory <b>{0}</b> is not" |
2964 " writable.</p>") | 3112 " writable.</p>" |
2965 .format(self.ppath)) | 3113 ).format(self.ppath), |
3114 ) | |
2966 return | 3115 return |
2967 | 3116 |
2968 # read a user specific project file | 3117 # read a user specific project file |
2969 self.__readUserProperties() | 3118 self.__readUserProperties() |
2970 | 3119 |
2971 with EricOverrideCursor(): | 3120 with EricOverrideCursor(): |
2972 oldState = self.isDirty() | 3121 oldState = self.isDirty() |
2973 self.vcs = self.initVCS() | 3122 self.vcs = self.initVCS() |
2974 if self.vcs is None and self.isDirty() == oldState: | 3123 if self.vcs is None and self.isDirty() == oldState: |
2975 # check, if project is version controlled | 3124 # check, if project is version controlled |
2976 pluginManager = ericApp().getObject("PluginManager") | 3125 pluginManager = ericApp().getObject("PluginManager") |
2977 for indicator, vcsData in ( | 3126 for ( |
2978 pluginManager.getVcsSystemIndicators().items() | 3127 indicator, |
2979 ): | 3128 vcsData, |
2980 if os.path.exists( | 3129 ) in pluginManager.getVcsSystemIndicators().items(): |
2981 os.path.join(self.ppath, indicator)): | 3130 if os.path.exists(os.path.join(self.ppath, indicator)): |
2982 if len(vcsData) > 1: | 3131 if len(vcsData) > 1: |
2983 vcsList = [] | 3132 vcsList = [] |
2984 for ( | 3133 for (_vcsSystemStr, vcsSystemDisplay) in vcsData: |
2985 _vcsSystemStr, vcsSystemDisplay | |
2986 ) in vcsData: | |
2987 vcsList.append(vcsSystemDisplay) | 3134 vcsList.append(vcsSystemDisplay) |
2988 with EricOverridenCursor(): | 3135 with EricOverridenCursor(): |
2989 res, vcs_ok = QInputDialog.getItem( | 3136 res, vcs_ok = QInputDialog.getItem( |
2990 None, | 3137 None, |
2991 self.tr("New Project"), | 3138 self.tr("New Project"), |
2992 self.tr( | 3139 self.tr("Select Version Control" " System"), |
2993 "Select Version Control" | |
2994 " System"), | |
2995 vcsList, | 3140 vcsList, |
2996 0, False) | 3141 0, |
3142 False, | |
3143 ) | |
2997 if vcs_ok: | 3144 if vcs_ok: |
2998 for ( | 3145 for (vcsSystemStr, vcsSystemDisplay) in vcsData: |
2999 vcsSystemStr, vcsSystemDisplay | |
3000 ) in vcsData: | |
3001 if res == vcsSystemDisplay: | 3146 if res == vcsSystemDisplay: |
3002 vcsSystem = vcsSystemStr | 3147 vcsSystem = vcsSystemStr |
3003 break | 3148 break |
3004 else: | 3149 else: |
3005 vcsSystem = "None" | 3150 vcsSystem = "None" |
3008 else: | 3153 else: |
3009 vcsSystem = vcsData[0][0] | 3154 vcsSystem = vcsData[0][0] |
3010 self.pdata["VCS"] = vcsSystem | 3155 self.pdata["VCS"] = vcsSystem |
3011 self.vcs = self.initVCS() | 3156 self.vcs = self.initVCS() |
3012 self.setDirty(True) | 3157 self.setDirty(True) |
3013 if ( | 3158 if self.vcs is not None and ( |
3014 self.vcs is not None and | 3159 self.vcs.vcsRegisteredState(self.ppath) |
3015 (self.vcs.vcsRegisteredState(self.ppath) != | 3160 != self.vcs.canBeCommitted |
3016 self.vcs.canBeCommitted) | |
3017 ): | 3161 ): |
3018 self.pdata["VCS"] = 'None' | 3162 self.pdata["VCS"] = "None" |
3019 self.vcs = self.initVCS() | 3163 self.vcs = self.initVCS() |
3020 self.closeAct.setEnabled(True) | 3164 self.closeAct.setEnabled(True) |
3021 self.saveasAct.setEnabled(True) | 3165 self.saveasAct.setEnabled(True) |
3022 self.actGrp2.setEnabled(True) | 3166 self.actGrp2.setEnabled(True) |
3023 self.propsAct.setEnabled(True) | 3167 self.propsAct.setEnabled(True) |
3031 self.menuCheckAct.setEnabled(True) | 3175 self.menuCheckAct.setEnabled(True) |
3032 self.menuShowAct.setEnabled(True) | 3176 self.menuShowAct.setEnabled(True) |
3033 self.menuDiagramAct.setEnabled(True) | 3177 self.menuDiagramAct.setEnabled(True) |
3034 self.menuApidocAct.setEnabled(True) | 3178 self.menuApidocAct.setEnabled(True) |
3035 self.menuPackagersAct.setEnabled(True) | 3179 self.menuPackagersAct.setEnabled(True) |
3036 self.pluginGrp.setEnabled( | 3180 self.pluginGrp.setEnabled(self.pdata["PROJECTTYPE"] in ["E7Plugin"]) |
3037 self.pdata["PROJECTTYPE"] in ["E7Plugin"]) | |
3038 self.addLanguageAct.setEnabled( | 3181 self.addLanguageAct.setEnabled( |
3039 bool(self.pdata["TRANSLATIONPATTERN"])) | 3182 bool(self.pdata["TRANSLATIONPATTERN"]) |
3040 self.makeGrp.setEnabled( | 3183 ) |
3041 self.pdata["MAKEPARAMS"]["MakeEnabled"]) | 3184 self.makeGrp.setEnabled(self.pdata["MAKEPARAMS"]["MakeEnabled"]) |
3042 self.menuMakeAct.setEnabled( | 3185 self.menuMakeAct.setEnabled(self.pdata["MAKEPARAMS"]["MakeEnabled"]) |
3043 self.pdata["MAKEPARAMS"]["MakeEnabled"]) | |
3044 self.menuOtherToolsAct.setEnabled(True) | 3186 self.menuOtherToolsAct.setEnabled(True) |
3045 self.menuFormattingAct.setEnabled(True) | 3187 self.menuFormattingAct.setEnabled(True) |
3046 | 3188 |
3047 # open a project debugger properties file being quiet | 3189 # open a project debugger properties file being quiet |
3048 # about errors | 3190 # about errors |
3049 if Preferences.getProject("AutoLoadDbgProperties"): | 3191 if Preferences.getProject("AutoLoadDbgProperties"): |
3050 self.__readDebugProperties(True) | 3192 self.__readDebugProperties(True) |
3051 | 3193 |
3052 self.__model.projectOpened() | 3194 self.__model.projectOpened() |
3053 self.projectOpenedHooks.emit() | 3195 self.projectOpenedHooks.emit() |
3054 self.projectOpened.emit() | 3196 self.projectOpened.emit() |
3055 | 3197 |
3056 if Preferences.getProject("SearchNewFiles"): | 3198 if Preferences.getProject("SearchNewFiles"): |
3057 self.__doSearchNewFiles() | 3199 self.__doSearchNewFiles() |
3058 | 3200 |
3059 # read a project tasks file | 3201 # read a project tasks file |
3060 self.__readTasks() | 3202 self.__readTasks() |
3061 self.ui.taskViewer.setProjectOpen(True) | 3203 self.ui.taskViewer.setProjectOpen(True) |
3062 # rescan project tasks | 3204 # rescan project tasks |
3063 if Preferences.getProject("TasksProjectRescanOnOpen"): | 3205 if Preferences.getProject("TasksProjectRescanOnOpen"): |
3064 ericApp().getObject("TaskViewer" | 3206 ericApp().getObject("TaskViewer").regenerateProjectTasks(quiet=True) |
3065 ).regenerateProjectTasks(quiet=True) | 3207 |
3066 | |
3067 if restoreSession: | 3208 if restoreSession: |
3068 # open the main script | 3209 # open the main script |
3069 if self.pdata["MAINSCRIPT"]: | 3210 if self.pdata["MAINSCRIPT"]: |
3070 if not os.path.isabs(self.pdata["MAINSCRIPT"]): | 3211 if not os.path.isabs(self.pdata["MAINSCRIPT"]): |
3071 ms = os.path.join( | 3212 ms = os.path.join(self.ppath, self.pdata["MAINSCRIPT"]) |
3072 self.ppath, self.pdata["MAINSCRIPT"]) | |
3073 else: | 3213 else: |
3074 ms = self.pdata["MAINSCRIPT"] | 3214 ms = self.pdata["MAINSCRIPT"] |
3075 self.sourceFile.emit(ms) | 3215 self.sourceFile.emit(ms) |
3076 | 3216 |
3077 # open a project session file being quiet about errors | 3217 # open a project session file being quiet about errors |
3078 if reopen: | 3218 if reopen: |
3079 self.__readSession(quiet=True, indicator="_tmp") | 3219 self.__readSession(quiet=True, indicator="_tmp") |
3080 elif Preferences.getProject("AutoLoadSession"): | 3220 elif Preferences.getProject("AutoLoadSession"): |
3081 self.__readSession(quiet=True) | 3221 self.__readSession(quiet=True) |
3082 | 3222 |
3083 # start the VCS monitor thread | 3223 # start the VCS monitor thread |
3084 self.__vcsConnectStatusMonitor() | 3224 self.__vcsConnectStatusMonitor() |
3085 | 3225 |
3086 def reopenProject(self): | 3226 def reopenProject(self): |
3087 """ | 3227 """ |
3088 Public slot to reopen the current project. | 3228 Public slot to reopen the current project. |
3089 """ | 3229 """ |
3090 projectFile = self.pfile | 3230 projectFile = self.pfile |
3091 res = self.closeProject(reopen=True) | 3231 res = self.closeProject(reopen=True) |
3092 if res: | 3232 if res: |
3093 self.openProject(projectFile, reopen=True) | 3233 self.openProject(projectFile, reopen=True) |
3094 | 3234 |
3095 def saveProject(self): | 3235 def saveProject(self): |
3096 """ | 3236 """ |
3097 Public slot to save the current project. | 3237 Public slot to save the current project. |
3098 | 3238 |
3099 @return flag indicating success | 3239 @return flag indicating success |
3100 """ | 3240 """ |
3101 if self.isDirty(): | 3241 if self.isDirty(): |
3102 if len(self.pfile) > 0: | 3242 if len(self.pfile) > 0: |
3103 if self.pfile.endswith(".e4p"): | 3243 if self.pfile.endswith(".e4p"): |
3109 else: | 3249 else: |
3110 ok = True | 3250 ok = True |
3111 self.sessActGrp.setEnabled(ok) | 3251 self.sessActGrp.setEnabled(ok) |
3112 self.menuSessionAct.setEnabled(ok) | 3252 self.menuSessionAct.setEnabled(ok) |
3113 return ok | 3253 return ok |
3114 | 3254 |
3115 def saveProjectAs(self): | 3255 def saveProjectAs(self): |
3116 """ | 3256 """ |
3117 Public slot to save the current project to a different file. | 3257 Public slot to save the current project to a different file. |
3118 | 3258 |
3119 @return flag indicating success (boolean) | 3259 @return flag indicating success (boolean) |
3120 """ | 3260 """ |
3121 defaultFilter = self.tr("Project Files (*.epj)") | 3261 defaultFilter = self.tr("Project Files (*.epj)") |
3122 defaultPath = ( | 3262 defaultPath = ( |
3123 self.ppath | 3263 self.ppath |
3124 if self.ppath else | 3264 if self.ppath |
3125 (Preferences.getMultiProject("Workspace") or | 3265 else (Preferences.getMultiProject("Workspace") or Utilities.getHomeDir()) |
3126 Utilities.getHomeDir()) | |
3127 ) | 3266 ) |
3128 fn, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( | 3267 fn, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( |
3129 self.parent(), | 3268 self.parent(), |
3130 self.tr("Save Project"), | 3269 self.tr("Save Project"), |
3131 defaultPath, | 3270 defaultPath, |
3132 self.tr("Project Files (*.epj)"), | 3271 self.tr("Project Files (*.epj)"), |
3133 defaultFilter, | 3272 defaultFilter, |
3134 EricFileDialog.DontConfirmOverwrite) | 3273 EricFileDialog.DontConfirmOverwrite, |
3135 | 3274 ) |
3275 | |
3136 if fn: | 3276 if fn: |
3137 fpath = pathlib.Path(fn) | 3277 fpath = pathlib.Path(fn) |
3138 if not fpath.suffix: | 3278 if not fpath.suffix: |
3139 ex = selectedFilter.split("(*")[1].split(")")[0] | 3279 ex = selectedFilter.split("(*")[1].split(")")[0] |
3140 if ex: | 3280 if ex: |
3141 fpath = fpath.with_suffix(ex) | 3281 fpath = fpath.with_suffix(ex) |
3142 if fpath.exists(): | 3282 if fpath.exists(): |
3143 res = EricMessageBox.yesNo( | 3283 res = EricMessageBox.yesNo( |
3144 self.ui, | 3284 self.ui, |
3145 self.tr("Save File"), | 3285 self.tr("Save File"), |
3146 self.tr("""<p>The file <b>{0}</b> already exists.""" | 3286 self.tr( |
3147 """ Overwrite it?</p>""").format(fpath), | 3287 """<p>The file <b>{0}</b> already exists.""" |
3148 icon=EricMessageBox.Warning) | 3288 """ Overwrite it?</p>""" |
3289 ).format(fpath), | |
3290 icon=EricMessageBox.Warning, | |
3291 ) | |
3149 if not res: | 3292 if not res: |
3150 return False | 3293 return False |
3151 | 3294 |
3152 self.name = fpath.stem | 3295 self.name = fpath.stem |
3153 ok = self.__writeProject(str(fpath)) | 3296 ok = self.__writeProject(str(fpath)) |
3154 | 3297 |
3155 if ok: | 3298 if ok: |
3156 # create management directory if not present | 3299 # create management directory if not present |
3157 self.createProjectManagementDir() | 3300 self.createProjectManagementDir() |
3158 | 3301 |
3159 # now save the tasks | 3302 # now save the tasks |
3160 self.writeTasks() | 3303 self.writeTasks() |
3161 | 3304 |
3162 self.sessActGrp.setEnabled(ok) | 3305 self.sessActGrp.setEnabled(ok) |
3163 self.menuSessionAct.setEnabled(ok) | 3306 self.menuSessionAct.setEnabled(ok) |
3164 self.projectClosedHooks.emit() | 3307 self.projectClosedHooks.emit() |
3165 self.projectClosed.emit(False) | 3308 self.projectClosed.emit(False) |
3166 self.projectOpenedHooks.emit() | 3309 self.projectOpenedHooks.emit() |
3167 self.projectOpened.emit() | 3310 self.projectOpened.emit() |
3168 return ok | 3311 return ok |
3169 else: | 3312 else: |
3170 return False | 3313 return False |
3171 | 3314 |
3172 def checkDirty(self): | 3315 def checkDirty(self): |
3173 """ | 3316 """ |
3174 Public method to check dirty status and open a message window. | 3317 Public method to check dirty status and open a message window. |
3175 | 3318 |
3176 @return flag indicating whether this operation was successful (boolean) | 3319 @return flag indicating whether this operation was successful (boolean) |
3177 """ | 3320 """ |
3178 if self.isDirty(): | 3321 if self.isDirty(): |
3179 res = EricMessageBox.okToClearData( | 3322 res = EricMessageBox.okToClearData( |
3180 self.parent(), | 3323 self.parent(), |
3181 self.tr("Close Project"), | 3324 self.tr("Close Project"), |
3182 self.tr("The current project has unsaved changes."), | 3325 self.tr("The current project has unsaved changes."), |
3183 self.saveProject) | 3326 self.saveProject, |
3327 ) | |
3184 if res: | 3328 if res: |
3185 self.setDirty(False) | 3329 self.setDirty(False) |
3186 return res | 3330 return res |
3187 | 3331 |
3188 return True | 3332 return True |
3189 | 3333 |
3190 def __closeAllWindows(self): | 3334 def __closeAllWindows(self): |
3191 """ | 3335 """ |
3192 Private method to close all project related windows. | 3336 Private method to close all project related windows. |
3193 """ | 3337 """ |
3194 self.codemetrics and self.codemetrics.close() | 3338 self.codemetrics and self.codemetrics.close() |
3195 self.codecoverage and self.codecoverage.close() | 3339 self.codecoverage and self.codecoverage.close() |
3196 self.profiledata and self.profiledata.close() | 3340 self.profiledata and self.profiledata.close() |
3197 self.applicationDiagram and self.applicationDiagram.close() | 3341 self.applicationDiagram and self.applicationDiagram.close() |
3198 self.loadedDiagram and self.loadedDiagram.close() | 3342 self.loadedDiagram and self.loadedDiagram.close() |
3199 | 3343 |
3200 @pyqtSlot() | 3344 @pyqtSlot() |
3201 def closeProject(self, reopen=False, noSave=False, shutdown=False): | 3345 def closeProject(self, reopen=False, noSave=False, shutdown=False): |
3202 """ | 3346 """ |
3203 Public slot to close the current project. | 3347 Public slot to close the current project. |
3204 | 3348 |
3205 @param reopen flag indicating a reopening of the project | 3349 @param reopen flag indicating a reopening of the project |
3206 @type bool | 3350 @type bool |
3207 @param noSave flag indicating to not perform save actions | 3351 @param noSave flag indicating to not perform save actions |
3208 @type bool | 3352 @type bool |
3209 @param shutdown flag indicating the IDE shutdown | 3353 @param shutdown flag indicating the IDE shutdown |
3211 @return flag indicating success | 3355 @return flag indicating success |
3212 @rtype bool | 3356 @rtype bool |
3213 """ | 3357 """ |
3214 # save the list of recently opened projects | 3358 # save the list of recently opened projects |
3215 self.__saveRecent() | 3359 self.__saveRecent() |
3216 | 3360 |
3217 if not self.isOpen(): | 3361 if not self.isOpen(): |
3218 return True | 3362 return True |
3219 | 3363 |
3220 if not self.checkDirty(): | 3364 if not self.checkDirty(): |
3221 return False | 3365 return False |
3222 | 3366 |
3223 ericApp().getObject("TaskViewer").stopProjectTaskExtraction() | 3367 ericApp().getObject("TaskViewer").stopProjectTaskExtraction() |
3224 | 3368 |
3225 # save the user project properties | 3369 # save the user project properties |
3226 if not noSave: | 3370 if not noSave: |
3227 self.__writeUserProperties() | 3371 self.__writeUserProperties() |
3228 | 3372 |
3229 # save the project session file being quiet about error | 3373 # save the project session file being quiet about error |
3230 if reopen: | 3374 if reopen: |
3231 self.__writeSession(quiet=True, indicator="_tmp") | 3375 self.__writeSession(quiet=True, indicator="_tmp") |
3232 elif Preferences.getProject("AutoSaveSession") and not noSave: | 3376 elif Preferences.getProject("AutoSaveSession") and not noSave: |
3233 self.__writeSession(quiet=True) | 3377 self.__writeSession(quiet=True) |
3234 | 3378 |
3235 # save the project debugger properties file being quiet about error | 3379 # save the project debugger properties file being quiet about error |
3236 if ( | 3380 if ( |
3237 Preferences.getProject("AutoSaveDbgProperties") and | 3381 Preferences.getProject("AutoSaveDbgProperties") |
3238 self.isDebugPropertiesLoaded() and | 3382 and self.isDebugPropertiesLoaded() |
3239 not noSave and self.debugPropertiesChanged | 3383 and not noSave |
3384 and self.debugPropertiesChanged | |
3240 ): | 3385 ): |
3241 self.__writeDebugProperties(True) | 3386 self.__writeDebugProperties(True) |
3242 | 3387 |
3243 vm = ericApp().getObject("ViewManager") | 3388 vm = ericApp().getObject("ViewManager") |
3244 | 3389 |
3245 # check dirty status of all project files first | 3390 # check dirty status of all project files first |
3246 for fn in vm.getOpenFilenames(): | 3391 for fn in vm.getOpenFilenames(): |
3247 if self.isProjectFile(fn): | 3392 if self.isProjectFile(fn): |
3248 reset = vm.checkFileDirty(fn) | 3393 reset = vm.checkFileDirty(fn) |
3249 if not reset: | 3394 if not reset: |
3250 # abort shutting down | 3395 # abort shutting down |
3251 return False | 3396 return False |
3252 | 3397 |
3253 # close all project related editors | 3398 # close all project related editors |
3254 success = True | 3399 success = True |
3255 for fn in vm.getOpenFilenames(): | 3400 for fn in vm.getOpenFilenames(): |
3256 if self.isProjectFile(fn): | 3401 if self.isProjectFile(fn): |
3257 success &= vm.closeWindow(fn, ignoreDirty=True) | 3402 success &= vm.closeWindow(fn, ignoreDirty=True) |
3258 if not success: | 3403 if not success: |
3259 return False | 3404 return False |
3260 | 3405 |
3261 # stop the VCS monitor thread | 3406 # stop the VCS monitor thread |
3262 if self.vcs is not None: | 3407 if self.vcs is not None: |
3263 self.vcs.stopStatusMonitor() | 3408 self.vcs.stopStatusMonitor() |
3264 | 3409 |
3265 # now save the tasks | 3410 # now save the tasks |
3266 if not noSave: | 3411 if not noSave: |
3267 self.writeTasks() | 3412 self.writeTasks() |
3268 self.ui.taskViewer.clearProjectTasks() | 3413 self.ui.taskViewer.clearProjectTasks() |
3269 self.ui.taskViewer.setProjectOpen(False) | 3414 self.ui.taskViewer.setProjectOpen(False) |
3270 | 3415 |
3271 # now shutdown the vcs interface | 3416 # now shutdown the vcs interface |
3272 if self.vcs: | 3417 if self.vcs: |
3273 self.vcs.vcsShutdown() | 3418 self.vcs.vcsShutdown() |
3274 self.vcs.deleteLater() | 3419 self.vcs.deleteLater() |
3275 self.vcs = None | 3420 self.vcs = None |
3276 ericApp().getObject("PluginManager").deactivateVcsPlugins() | 3421 ericApp().getObject("PluginManager").deactivateVcsPlugins() |
3277 | 3422 |
3278 # now close all project related tool windows | 3423 # now close all project related tool windows |
3279 self.__closeAllWindows() | 3424 self.__closeAllWindows() |
3280 | 3425 |
3281 self.__initData() | 3426 self.__initData() |
3282 self.closeAct.setEnabled(False) | 3427 self.closeAct.setEnabled(False) |
3283 self.saveasAct.setEnabled(False) | 3428 self.saveasAct.setEnabled(False) |
3284 self.saveAct.setEnabled(False) | 3429 self.saveAct.setEnabled(False) |
3285 self.actGrp2.setEnabled(False) | 3430 self.actGrp2.setEnabled(False) |
3299 self.pluginGrp.setEnabled(False) | 3444 self.pluginGrp.setEnabled(False) |
3300 self.makeGrp.setEnabled(False) | 3445 self.makeGrp.setEnabled(False) |
3301 self.menuMakeAct.setEnabled(False) | 3446 self.menuMakeAct.setEnabled(False) |
3302 self.menuOtherToolsAct.setEnabled(False) | 3447 self.menuOtherToolsAct.setEnabled(False) |
3303 self.menuFormattingAct.setEnabled(False) | 3448 self.menuFormattingAct.setEnabled(False) |
3304 | 3449 |
3305 self.__model.projectClosed() | 3450 self.__model.projectClosed() |
3306 self.projectClosedHooks.emit() | 3451 self.projectClosedHooks.emit() |
3307 self.projectClosed.emit(shutdown) | 3452 self.projectClosed.emit(shutdown) |
3308 | 3453 |
3309 return True | 3454 return True |
3310 | 3455 |
3311 def saveAllScripts(self, reportSyntaxErrors=False): | 3456 def saveAllScripts(self, reportSyntaxErrors=False): |
3312 """ | 3457 """ |
3313 Public method to save all scripts belonging to the project. | 3458 Public method to save all scripts belonging to the project. |
3314 | 3459 |
3315 @param reportSyntaxErrors flag indicating special reporting | 3460 @param reportSyntaxErrors flag indicating special reporting |
3316 for syntax errors (boolean) | 3461 for syntax errors (boolean) |
3317 @return flag indicating success (boolean) | 3462 @return flag indicating success (boolean) |
3318 """ | 3463 """ |
3319 vm = ericApp().getObject("ViewManager") | 3464 vm = ericApp().getObject("ViewManager") |
3324 if rfn in self.pdata["SOURCES"] or rfn in self.pdata["OTHERS"]: | 3469 if rfn in self.pdata["SOURCES"] or rfn in self.pdata["OTHERS"]: |
3325 editor = vm.getOpenEditor(fn) | 3470 editor = vm.getOpenEditor(fn) |
3326 success &= vm.saveEditorEd(editor) | 3471 success &= vm.saveEditorEd(editor) |
3327 if reportSyntaxErrors and editor.hasSyntaxErrors(): | 3472 if reportSyntaxErrors and editor.hasSyntaxErrors(): |
3328 filesWithSyntaxErrors += 1 | 3473 filesWithSyntaxErrors += 1 |
3329 | 3474 |
3330 if reportSyntaxErrors and filesWithSyntaxErrors > 0: | 3475 if reportSyntaxErrors and filesWithSyntaxErrors > 0: |
3331 EricMessageBox.critical( | 3476 EricMessageBox.critical( |
3332 self.ui, | 3477 self.ui, |
3333 self.tr("Syntax errors detected"), | 3478 self.tr("Syntax errors detected"), |
3334 self.tr( | 3479 self.tr( |
3335 """The project contains %n file(s) with syntax errors.""", | 3480 """The project contains %n file(s) with syntax errors.""", |
3336 "", filesWithSyntaxErrors) | 3481 "", |
3482 filesWithSyntaxErrors, | |
3483 ), | |
3337 ) | 3484 ) |
3338 return False | 3485 return False |
3339 else: | 3486 else: |
3340 return success | 3487 return success |
3341 | 3488 |
3342 def checkAllScriptsDirty(self, reportSyntaxErrors=False): | 3489 def checkAllScriptsDirty(self, reportSyntaxErrors=False): |
3343 """ | 3490 """ |
3344 Public method to check all scripts belonging to the project for | 3491 Public method to check all scripts belonging to the project for |
3345 their dirty status. | 3492 their dirty status. |
3346 | 3493 |
3347 @param reportSyntaxErrors flag indicating special reporting | 3494 @param reportSyntaxErrors flag indicating special reporting |
3348 for syntax errors (boolean) | 3495 for syntax errors (boolean) |
3349 @return flag indicating success (boolean) | 3496 @return flag indicating success (boolean) |
3350 """ | 3497 """ |
3351 vm = ericApp().getObject("ViewManager") | 3498 vm = ericApp().getObject("ViewManager") |
3356 if rfn in self.pdata["SOURCES"] or rfn in self.pdata["OTHERS"]: | 3503 if rfn in self.pdata["SOURCES"] or rfn in self.pdata["OTHERS"]: |
3357 editor = vm.getOpenEditor(fn) | 3504 editor = vm.getOpenEditor(fn) |
3358 success &= editor.checkDirty() | 3505 success &= editor.checkDirty() |
3359 if reportSyntaxErrors and editor.hasSyntaxErrors(): | 3506 if reportSyntaxErrors and editor.hasSyntaxErrors(): |
3360 filesWithSyntaxErrors += 1 | 3507 filesWithSyntaxErrors += 1 |
3361 | 3508 |
3362 if reportSyntaxErrors and filesWithSyntaxErrors > 0: | 3509 if reportSyntaxErrors and filesWithSyntaxErrors > 0: |
3363 EricMessageBox.critical( | 3510 EricMessageBox.critical( |
3364 self.ui, | 3511 self.ui, |
3365 self.tr("Syntax errors detected"), | 3512 self.tr("Syntax errors detected"), |
3366 self.tr( | 3513 self.tr( |
3367 """The project contains %n file(s) with syntax errors.""", | 3514 """The project contains %n file(s) with syntax errors.""", |
3368 "", filesWithSyntaxErrors) | 3515 "", |
3516 filesWithSyntaxErrors, | |
3517 ), | |
3369 ) | 3518 ) |
3370 return False | 3519 return False |
3371 else: | 3520 else: |
3372 return success | 3521 return success |
3373 | 3522 |
3374 def getMainScript(self, normalized=False): | 3523 def getMainScript(self, normalized=False): |
3375 """ | 3524 """ |
3376 Public method to return the main script filename. | 3525 Public method to return the main script filename. |
3377 | 3526 |
3378 The normalized name is the name of the main script prepended with | 3527 The normalized name is the name of the main script prepended with |
3379 the project path. | 3528 the project path. |
3380 | 3529 |
3381 @param normalized flag indicating a normalized filename is wanted | 3530 @param normalized flag indicating a normalized filename is wanted |
3382 @type bool | 3531 @type bool |
3383 @return filename of the projects main script | 3532 @return filename of the projects main script |
3384 @rtype str | 3533 @rtype str |
3385 """ | 3534 """ |
3388 return os.path.join(self.ppath, self.pdata["MAINSCRIPT"]) | 3537 return os.path.join(self.ppath, self.pdata["MAINSCRIPT"]) |
3389 else: | 3538 else: |
3390 return self.pdata["MAINSCRIPT"] | 3539 return self.pdata["MAINSCRIPT"] |
3391 else: | 3540 else: |
3392 return "" | 3541 return "" |
3393 | 3542 |
3394 def getSources(self, normalized=False): | 3543 def getSources(self, normalized=False): |
3395 """ | 3544 """ |
3396 Public method to return the source script files. | 3545 Public method to return the source script files. |
3397 | 3546 |
3398 @param normalized flag indicating a normalized filename is wanted | 3547 @param normalized flag indicating a normalized filename is wanted |
3399 @type bool | 3548 @type bool |
3400 @return list of the projects scripts | 3549 @return list of the projects scripts |
3401 @rtype list of str | 3550 @rtype list of str |
3402 """ | 3551 """ |
3403 return self.getProjectFiles("SOURCES", normalized=normalized) | 3552 return self.getProjectFiles("SOURCES", normalized=normalized) |
3404 | 3553 |
3405 def getProjectFiles(self, fileType, normalized=False): | 3554 def getProjectFiles(self, fileType, normalized=False): |
3406 """ | 3555 """ |
3407 Public method to get the file entries of the given type. | 3556 Public method to get the file entries of the given type. |
3408 | 3557 |
3409 @param fileType project file type (one of SOURCES, FORMS, RESOURCES, | 3558 @param fileType project file type (one of SOURCES, FORMS, RESOURCES, |
3410 INTERFACES, PROTOCOLS, OTHERS, TRANSLATIONS) | 3559 INTERFACES, PROTOCOLS, OTHERS, TRANSLATIONS) |
3411 @type str | 3560 @type str |
3412 @param normalized flag indicating normalized file names are wanted | 3561 @param normalized flag indicating normalized file names are wanted |
3413 @type boolean | 3562 @type boolean |
3414 @return list of file names | 3563 @return list of file names |
3415 @rtype list of str | 3564 @rtype list of str |
3416 @exception ValueError raised when an unsupported file type is given | 3565 @exception ValueError raised when an unsupported file type is given |
3417 """ | 3566 """ |
3418 if fileType not in ["SOURCES", "FORMS", "RESOURCES", "INTERFACES", | 3567 if fileType not in [ |
3419 "PROTOCOLS", "OTHERS", "TRANSLATIONS"]: | 3568 "SOURCES", |
3569 "FORMS", | |
3570 "RESOURCES", | |
3571 "INTERFACES", | |
3572 "PROTOCOLS", | |
3573 "OTHERS", | |
3574 "TRANSLATIONS", | |
3575 ]: | |
3420 raise ValueError("Given file type has incorrect value.") | 3576 raise ValueError("Given file type has incorrect value.") |
3421 | 3577 |
3422 if normalized: | 3578 if normalized: |
3423 return [os.path.join(self.ppath, fn) for fn in | 3579 return [os.path.join(self.ppath, fn) for fn in self.pdata[fileType]] |
3424 self.pdata[fileType]] | |
3425 else: | 3580 else: |
3426 return self.pdata[fileType] | 3581 return self.pdata[fileType] |
3427 | 3582 |
3428 def getProjectType(self): | 3583 def getProjectType(self): |
3429 """ | 3584 """ |
3430 Public method to get the type of the project. | 3585 Public method to get the type of the project. |
3431 | 3586 |
3432 @return UI type of the project (string) | 3587 @return UI type of the project (string) |
3433 """ | 3588 """ |
3434 return self.pdata["PROJECTTYPE"] | 3589 return self.pdata["PROJECTTYPE"] |
3435 | 3590 |
3436 def getProjectLanguage(self): | 3591 def getProjectLanguage(self): |
3437 """ | 3592 """ |
3438 Public method to get the project's programming language. | 3593 Public method to get the project's programming language. |
3439 | 3594 |
3440 @return programming language (string) | 3595 @return programming language (string) |
3441 """ | 3596 """ |
3442 return self.pdata["PROGLANGUAGE"] | 3597 return self.pdata["PROGLANGUAGE"] |
3443 | 3598 |
3444 def isMixedLanguageProject(self): | 3599 def isMixedLanguageProject(self): |
3445 """ | 3600 """ |
3446 Public method to check, if this is a mixed language project. | 3601 Public method to check, if this is a mixed language project. |
3447 | 3602 |
3448 @return flag indicating a mixed language project | 3603 @return flag indicating a mixed language project |
3449 @rtype bool | 3604 @rtype bool |
3450 """ | 3605 """ |
3451 return self.pdata["MIXEDLANGUAGE"] | 3606 return self.pdata["MIXEDLANGUAGE"] |
3452 | 3607 |
3453 def isPythonProject(self): | 3608 def isPythonProject(self): |
3454 """ | 3609 """ |
3455 Public method to check, if this project is a Python3 or MicroPython | 3610 Public method to check, if this project is a Python3 or MicroPython |
3456 project. | 3611 project. |
3457 | 3612 |
3458 @return flag indicating a Python project (boolean) | 3613 @return flag indicating a Python project (boolean) |
3459 """ | 3614 """ |
3460 return self.pdata["PROGLANGUAGE"] in ["Python3", "MicroPython"] | 3615 return self.pdata["PROGLANGUAGE"] in ["Python3", "MicroPython"] |
3461 | 3616 |
3462 def isPy3Project(self): | 3617 def isPy3Project(self): |
3463 """ | 3618 """ |
3464 Public method to check, if this project is a Python3 project. | 3619 Public method to check, if this project is a Python3 project. |
3465 | 3620 |
3466 @return flag indicating a Python3 project (boolean) | 3621 @return flag indicating a Python3 project (boolean) |
3467 """ | 3622 """ |
3468 return self.pdata["PROGLANGUAGE"] == "Python3" | 3623 return self.pdata["PROGLANGUAGE"] == "Python3" |
3469 | 3624 |
3470 def isMicroPythonProject(self): | 3625 def isMicroPythonProject(self): |
3471 """ | 3626 """ |
3472 Public method to check, if this project is a MicroPython project. | 3627 Public method to check, if this project is a MicroPython project. |
3473 | 3628 |
3474 @return flag indicating a MicroPython project | 3629 @return flag indicating a MicroPython project |
3475 @rtype bool | 3630 @rtype bool |
3476 """ | 3631 """ |
3477 return self.pdata["PROGLANGUAGE"] == "MicroPython" | 3632 return self.pdata["PROGLANGUAGE"] == "MicroPython" |
3478 | 3633 |
3479 def isRubyProject(self): | 3634 def isRubyProject(self): |
3480 """ | 3635 """ |
3481 Public method to check, if this project is a Ruby project. | 3636 Public method to check, if this project is a Ruby project. |
3482 | 3637 |
3483 @return flag indicating a Ruby project (boolean) | 3638 @return flag indicating a Ruby project (boolean) |
3484 """ | 3639 """ |
3485 return self.pdata["PROGLANGUAGE"] == "Ruby" | 3640 return self.pdata["PROGLANGUAGE"] == "Ruby" |
3486 | 3641 |
3487 def isJavaScriptProject(self): | 3642 def isJavaScriptProject(self): |
3488 """ | 3643 """ |
3489 Public method to check, if this project is a JavaScript project. | 3644 Public method to check, if this project is a JavaScript project. |
3490 | 3645 |
3491 @return flag indicating a JavaScript project (boolean) | 3646 @return flag indicating a JavaScript project (boolean) |
3492 """ | 3647 """ |
3493 return self.pdata["PROGLANGUAGE"] == "JavaScript" | 3648 return self.pdata["PROGLANGUAGE"] == "JavaScript" |
3494 | 3649 |
3495 def getProjectSpellLanguage(self): | 3650 def getProjectSpellLanguage(self): |
3496 """ | 3651 """ |
3497 Public method to get the project's programming language. | 3652 Public method to get the project's programming language. |
3498 | 3653 |
3499 @return programming language (string) | 3654 @return programming language (string) |
3500 """ | 3655 """ |
3501 return self.pdata["SPELLLANGUAGE"] | 3656 return self.pdata["SPELLLANGUAGE"] |
3502 | 3657 |
3503 def getProjectDictionaries(self): | 3658 def getProjectDictionaries(self): |
3504 """ | 3659 """ |
3505 Public method to get the names of the project specific dictionaries. | 3660 Public method to get the names of the project specific dictionaries. |
3506 | 3661 |
3507 @return tuple of two strings giving the absolute path names of the | 3662 @return tuple of two strings giving the absolute path names of the |
3508 project specific word and exclude list | 3663 project specific word and exclude list |
3509 """ | 3664 """ |
3510 pwl = "" | 3665 pwl = "" |
3511 if self.pdata["SPELLWORDS"]: | 3666 if self.pdata["SPELLWORDS"]: |
3512 pwl = os.path.join(self.ppath, self.pdata["SPELLWORDS"]) | 3667 pwl = os.path.join(self.ppath, self.pdata["SPELLWORDS"]) |
3513 if not os.path.isfile(pwl): | 3668 if not os.path.isfile(pwl): |
3514 pwl = "" | 3669 pwl = "" |
3515 | 3670 |
3516 pel = "" | 3671 pel = "" |
3517 if self.pdata["SPELLEXCLUDES"]: | 3672 if self.pdata["SPELLEXCLUDES"]: |
3518 pel = os.path.join(self.ppath, self.pdata["SPELLEXCLUDES"]) | 3673 pel = os.path.join(self.ppath, self.pdata["SPELLEXCLUDES"]) |
3519 if not os.path.isfile(pel): | 3674 if not os.path.isfile(pel): |
3520 pel = "" | 3675 pel = "" |
3521 | 3676 |
3522 return (pwl, pel) | 3677 return (pwl, pel) |
3523 | 3678 |
3524 def getDefaultSourceExtension(self): | 3679 def getDefaultSourceExtension(self): |
3525 """ | 3680 """ |
3526 Public method to get the default extension for the project's | 3681 Public method to get the default extension for the project's |
3527 programming language. | 3682 programming language. |
3528 | 3683 |
3529 @return default extension (including the dot) (string) | 3684 @return default extension (including the dot) (string) |
3530 """ | 3685 """ |
3531 lang = self.pdata["PROGLANGUAGE"] | 3686 lang = self.pdata["PROGLANGUAGE"] |
3532 if lang in ("", "Python"): | 3687 if lang in ("", "Python"): |
3533 lang = "Python3" | 3688 lang = "Python3" |
3534 return self.__sourceExtensions(lang)[0] | 3689 return self.__sourceExtensions(lang)[0] |
3535 | 3690 |
3536 def getProjectPath(self): | 3691 def getProjectPath(self): |
3537 """ | 3692 """ |
3538 Public method to get the project path. | 3693 Public method to get the project path. |
3539 | 3694 |
3540 @return project path (string) | 3695 @return project path (string) |
3541 """ | 3696 """ |
3542 return self.ppath | 3697 return self.ppath |
3543 | 3698 |
3544 def startswithProjectPath(self, path): | 3699 def startswithProjectPath(self, path): |
3545 """ | 3700 """ |
3546 Public method to check, if a path starts with the project path. | 3701 Public method to check, if a path starts with the project path. |
3547 | 3702 |
3548 @param path path to be checked | 3703 @param path path to be checked |
3549 @type str | 3704 @type str |
3550 @return flag indicating that the path starts with the project path | 3705 @return flag indicating that the path starts with the project path |
3551 @rtype bool | 3706 @rtype bool |
3552 """ | 3707 """ |
3553 return ( | 3708 return bool(self.ppath) and ( |
3554 bool(self.ppath) and | 3709 path == self.ppath |
3555 (path == self.ppath or | 3710 or Utilities.normcasepath(Utilities.toNativeSeparators(path)).startswith( |
3556 Utilities.normcasepath(Utilities.toNativeSeparators(path)) | 3711 Utilities.normcasepath(Utilities.toNativeSeparators(self.ppath + "/")) |
3557 .startswith(Utilities.normcasepath( | 3712 ) |
3558 Utilities.toNativeSeparators(self.ppath + "/"))) | 3713 ) |
3559 ) | 3714 |
3560 ) | |
3561 | |
3562 def getProjectFile(self): | 3715 def getProjectFile(self): |
3563 """ | 3716 """ |
3564 Public method to get the path of the project file. | 3717 Public method to get the path of the project file. |
3565 | 3718 |
3566 @return path of the project file (string) | 3719 @return path of the project file (string) |
3567 """ | 3720 """ |
3568 return self.pfile | 3721 return self.pfile |
3569 | 3722 |
3570 def getProjectName(self): | 3723 def getProjectName(self): |
3571 """ | 3724 """ |
3572 Public method to get the name of the project. | 3725 Public method to get the name of the project. |
3573 | 3726 |
3574 The project name is determined from the name of the project file. | 3727 The project name is determined from the name of the project file. |
3575 | 3728 |
3576 @return name of the project (string) | 3729 @return name of the project (string) |
3577 """ | 3730 """ |
3578 if self.pfile: | 3731 if self.pfile: |
3579 name = os.path.splitext(self.pfile)[0] | 3732 name = os.path.splitext(self.pfile)[0] |
3580 return os.path.basename(name) | 3733 return os.path.basename(name) |
3581 else: | 3734 else: |
3582 return "" | 3735 return "" |
3583 | 3736 |
3584 def getProjectManagementDir(self): | 3737 def getProjectManagementDir(self): |
3585 """ | 3738 """ |
3586 Public method to get the path of the management directory. | 3739 Public method to get the path of the management directory. |
3587 | 3740 |
3588 @return path of the management directory (string) | 3741 @return path of the management directory (string) |
3589 """ | 3742 """ |
3590 return os.path.join(self.ppath, ".eric7project") | 3743 return os.path.join(self.ppath, ".eric7project") |
3591 | 3744 |
3592 def createProjectManagementDir(self): | 3745 def createProjectManagementDir(self): |
3593 """ | 3746 """ |
3594 Public method to create the project management directory. | 3747 Public method to create the project management directory. |
3595 | 3748 |
3596 It does nothing, if it already exists. | 3749 It does nothing, if it already exists. |
3597 """ | 3750 """ |
3598 # create management directory if not present | 3751 # create management directory if not present |
3599 mgmtDir = self.getProjectManagementDir() | 3752 mgmtDir = self.getProjectManagementDir() |
3600 if not os.path.exists(mgmtDir): | 3753 if not os.path.exists(mgmtDir): |
3601 os.makedirs(mgmtDir) | 3754 os.makedirs(mgmtDir) |
3602 | 3755 |
3603 def getHash(self): | 3756 def getHash(self): |
3604 """ | 3757 """ |
3605 Public method to get the project hash. | 3758 Public method to get the project hash. |
3606 | 3759 |
3607 @return project hash as a hex string (string) | 3760 @return project hash as a hex string (string) |
3608 """ | 3761 """ |
3609 return self.pdata["HASH"] | 3762 return self.pdata["HASH"] |
3610 | 3763 |
3611 def getRelativePath(self, path): | 3764 def getRelativePath(self, path): |
3612 """ | 3765 """ |
3613 Public method to convert a file path to a project relative | 3766 Public method to convert a file path to a project relative |
3614 file path. | 3767 file path. |
3615 | 3768 |
3616 @param path file or directory name to convert (string) | 3769 @param path file or directory name to convert (string) |
3617 @return project relative path or unchanged path, if path doesn't | 3770 @return project relative path or unchanged path, if path doesn't |
3618 belong to the project (string) | 3771 belong to the project (string) |
3619 """ | 3772 """ |
3620 try: | 3773 try: |
3621 return str(pathlib.Path(path).relative_to(self.ppath)) | 3774 return str(pathlib.Path(path).relative_to(self.ppath)) |
3622 except ValueError: | 3775 except ValueError: |
3623 return path | 3776 return path |
3624 | 3777 |
3625 def getRelativeUniversalPath(self, path): | 3778 def getRelativeUniversalPath(self, path): |
3626 """ | 3779 """ |
3627 Public method to convert a file path to a project relative | 3780 Public method to convert a file path to a project relative |
3628 file path with universal separators. | 3781 file path with universal separators. |
3629 | 3782 |
3630 @param path file or directory name to convert (string) | 3783 @param path file or directory name to convert (string) |
3631 @return project relative path or unchanged path, if path doesn't | 3784 @return project relative path or unchanged path, if path doesn't |
3632 belong to the project (string) | 3785 belong to the project (string) |
3633 """ | 3786 """ |
3634 return Utilities.fromNativeSeparators(self.getRelativePath(path)) | 3787 return Utilities.fromNativeSeparators(self.getRelativePath(path)) |
3635 | 3788 |
3636 def getAbsolutePath(self, fn): | 3789 def getAbsolutePath(self, fn): |
3637 """ | 3790 """ |
3638 Public method to convert a project relative file path to an absolute | 3791 Public method to convert a project relative file path to an absolute |
3639 file path. | 3792 file path. |
3640 | 3793 |
3641 @param fn file or directory name to convert (string) | 3794 @param fn file or directory name to convert (string) |
3642 @return absolute path (string) | 3795 @return absolute path (string) |
3643 """ | 3796 """ |
3644 if not os.path.isabs(fn): | 3797 if not os.path.isabs(fn): |
3645 fn = os.path.join(self.ppath, fn) | 3798 fn = os.path.join(self.ppath, fn) |
3646 return fn | 3799 return fn |
3647 | 3800 |
3648 def getAbsoluteUniversalPath(self, fn): | 3801 def getAbsoluteUniversalPath(self, fn): |
3649 """ | 3802 """ |
3650 Public method to convert a project relative file path with universal | 3803 Public method to convert a project relative file path with universal |
3651 separators to an absolute file path. | 3804 separators to an absolute file path. |
3652 | 3805 |
3653 @param fn file or directory name to convert (string) | 3806 @param fn file or directory name to convert (string) |
3654 @return absolute path (string) | 3807 @return absolute path (string) |
3655 """ | 3808 """ |
3656 if not os.path.isabs(fn): | 3809 if not os.path.isabs(fn): |
3657 fn = os.path.join(self.ppath, Utilities.toNativeSeparators(fn)) | 3810 fn = os.path.join(self.ppath, Utilities.toNativeSeparators(fn)) |
3658 return fn | 3811 return fn |
3659 | 3812 |
3660 def getEolString(self): | 3813 def getEolString(self): |
3661 """ | 3814 """ |
3662 Public method to get the EOL-string to be used by the project. | 3815 Public method to get the EOL-string to be used by the project. |
3663 | 3816 |
3664 @return eol string (string) | 3817 @return eol string (string) |
3665 """ | 3818 """ |
3666 if self.pdata["EOL"] >= 0: | 3819 if self.pdata["EOL"] >= 0: |
3667 return self.eols[self.pdata["EOL"]] | 3820 return self.eols[self.pdata["EOL"]] |
3668 else: | 3821 else: |
3669 eolMode = Preferences.getEditor("EOLMode") | 3822 eolMode = Preferences.getEditor("EOLMode") |
3670 if eolMode == QsciScintilla.EolMode.EolWindows: | 3823 if eolMode == QsciScintilla.EolMode.EolWindows: |
3671 eol = '\r\n' | 3824 eol = "\r\n" |
3672 elif eolMode == QsciScintilla.EolMode.EolUnix: | 3825 elif eolMode == QsciScintilla.EolMode.EolUnix: |
3673 eol = '\n' | 3826 eol = "\n" |
3674 elif eolMode == QsciScintilla.EolMode.EolMac: | 3827 elif eolMode == QsciScintilla.EolMode.EolMac: |
3675 eol = '\r' | 3828 eol = "\r" |
3676 else: | 3829 else: |
3677 eol = os.linesep | 3830 eol = os.linesep |
3678 return eol | 3831 return eol |
3679 | 3832 |
3680 def useSystemEol(self): | 3833 def useSystemEol(self): |
3681 """ | 3834 """ |
3682 Public method to check, if the project uses the system eol setting. | 3835 Public method to check, if the project uses the system eol setting. |
3683 | 3836 |
3684 @return flag indicating the usage of system eol (boolean) | 3837 @return flag indicating the usage of system eol (boolean) |
3685 """ | 3838 """ |
3686 return self.pdata["EOL"] == 0 | 3839 return self.pdata["EOL"] == 0 |
3687 | 3840 |
3688 def getProjectVersion(self): | 3841 def getProjectVersion(self): |
3689 """ | 3842 """ |
3690 Public mehod to get the version number of the project. | 3843 Public mehod to get the version number of the project. |
3691 | 3844 |
3692 @return version number | 3845 @return version number |
3693 @rtype str | 3846 @rtype str |
3694 """ | 3847 """ |
3695 return self.pdata["VERSION"] | 3848 return self.pdata["VERSION"] |
3696 | 3849 |
3697 def getProjectAuthor(self): | 3850 def getProjectAuthor(self): |
3698 """ | 3851 """ |
3699 Public method to get the author of the project. | 3852 Public method to get the author of the project. |
3700 | 3853 |
3701 @return author name | 3854 @return author name |
3702 @rtype str | 3855 @rtype str |
3703 """ | 3856 """ |
3704 return self.pdata["AUTHOR"] | 3857 return self.pdata["AUTHOR"] |
3705 | 3858 |
3706 def getProjectAuthorEmail(self): | 3859 def getProjectAuthorEmail(self): |
3707 """ | 3860 """ |
3708 Public method to get the email address of the project author. | 3861 Public method to get the email address of the project author. |
3709 | 3862 |
3710 @return project author email | 3863 @return project author email |
3711 @rtype str | 3864 @rtype str |
3712 """ | 3865 """ |
3713 return self.pdata["EMAIL"] | 3866 return self.pdata["EMAIL"] |
3714 | 3867 |
3715 def getProjectDescription(self): | 3868 def getProjectDescription(self): |
3716 """ | 3869 """ |
3717 Public method to get the description of the project. | 3870 Public method to get the description of the project. |
3718 | 3871 |
3719 @return project description | 3872 @return project description |
3720 @rtype str | 3873 @rtype str |
3721 """ | 3874 """ |
3722 return self.pdata["DESCRIPTION"] | 3875 return self.pdata["DESCRIPTION"] |
3723 | 3876 |
3724 def getProjectVenv(self, resolveDebugger=True): | 3877 def getProjectVenv(self, resolveDebugger=True): |
3725 """ | 3878 """ |
3726 Public method to get the name of the virtual environment used by the | 3879 Public method to get the name of the virtual environment used by the |
3727 project. | 3880 project. |
3728 | 3881 |
3729 @param resolveDebugger flag indicating to resolve the virtual | 3882 @param resolveDebugger flag indicating to resolve the virtual |
3730 environment name via the debugger settings if none was configured | 3883 environment name via the debugger settings if none was configured |
3731 @type bool | 3884 @type bool |
3732 @return name of the project's virtual environment | 3885 @return name of the project's virtual environment |
3733 @rtype str | 3886 @rtype str |
3734 """ | 3887 """ |
3735 venvName = self.getDebugProperty("VIRTUALENV") | 3888 venvName = self.getDebugProperty("VIRTUALENV") |
3736 if ( | 3889 if ( |
3737 not venvName and | 3890 not venvName |
3738 resolveDebugger and | 3891 and resolveDebugger |
3739 self.getProjectLanguage() in ("Python3", "MicroPython", "Cython") | 3892 and self.getProjectLanguage() in ("Python3", "MicroPython", "Cython") |
3740 ): | 3893 ): |
3741 venvName = Preferences.getDebugger("Python3VirtualEnv") | 3894 venvName = Preferences.getDebugger("Python3VirtualEnv") |
3742 | 3895 |
3743 return venvName | 3896 return venvName |
3744 | 3897 |
3745 def getProjectInterpreter(self, resolveGlobal=True): | 3898 def getProjectInterpreter(self, resolveGlobal=True): |
3746 """ | 3899 """ |
3747 Public method to get the path of the interpreter used by the project. | 3900 Public method to get the path of the interpreter used by the project. |
3748 | 3901 |
3749 @param resolveGlobal flag indicating to resolve the interpreter using | 3902 @param resolveGlobal flag indicating to resolve the interpreter using |
3750 the global interpreter if no project of debugger specific | 3903 the global interpreter if no project of debugger specific |
3751 environment was configured | 3904 environment was configured |
3752 @type bool | 3905 @type bool |
3753 @return path of the project's interpreter | 3906 @return path of the project's interpreter |
3755 """ | 3908 """ |
3756 interpreter = "" | 3909 interpreter = "" |
3757 venvName = self.getProjectVenv() | 3910 venvName = self.getProjectVenv() |
3758 if venvName: | 3911 if venvName: |
3759 interpreter = ( | 3912 interpreter = ( |
3760 ericApp().getObject("VirtualEnvManager") | 3913 ericApp() |
3914 .getObject("VirtualEnvManager") | |
3761 .getVirtualenvInterpreter(venvName) | 3915 .getVirtualenvInterpreter(venvName) |
3762 ) | 3916 ) |
3763 if not interpreter and resolveGlobal: | 3917 if not interpreter and resolveGlobal: |
3764 interpreter = Globals.getPythonExecutable() | 3918 interpreter = Globals.getPythonExecutable() |
3765 | 3919 |
3766 return interpreter | 3920 return interpreter |
3767 | 3921 |
3768 def getProjectExecPath(self): | 3922 def getProjectExecPath(self): |
3769 """ | 3923 """ |
3770 Public method to get the executable search path prefix of the project. | 3924 Public method to get the executable search path prefix of the project. |
3771 | 3925 |
3772 @return executable search path prefix | 3926 @return executable search path prefix |
3773 @rtype str | 3927 @rtype str |
3774 """ | 3928 """ |
3775 execPath = "" | 3929 execPath = "" |
3776 venvName = self.getProjectVenv() | 3930 venvName = self.getProjectVenv() |
3777 if venvName: | 3931 if venvName: |
3778 execPath = ( | 3932 execPath = ( |
3779 ericApp().getObject("VirtualEnvManager") | 3933 ericApp().getObject("VirtualEnvManager").getVirtualenvExecPath(venvName) |
3780 .getVirtualenvExecPath(venvName) | 3934 ) |
3781 ) | 3935 |
3782 | |
3783 return execPath | 3936 return execPath |
3784 | 3937 |
3785 def getProjectTestingFramework(self): | 3938 def getProjectTestingFramework(self): |
3786 """ | 3939 """ |
3787 Public method to get the testing framework name of the project. | 3940 Public method to get the testing framework name of the project. |
3788 | 3941 |
3789 @return testing framework name of the project | 3942 @return testing framework name of the project |
3790 @rtype str | 3943 @rtype str |
3791 """ | 3944 """ |
3792 try: | 3945 try: |
3793 return self.pdata["TESTING_FRAMEWORK"] | 3946 return self.pdata["TESTING_FRAMEWORK"] |
3794 except KeyError: | 3947 except KeyError: |
3795 return "" | 3948 return "" |
3796 | 3949 |
3797 def getProjectLicense(self): | 3950 def getProjectLicense(self): |
3798 """ | 3951 """ |
3799 Public method to get the license type used by the project. | 3952 Public method to get the license type used by the project. |
3800 | 3953 |
3801 @return license type of the project | 3954 @return license type of the project |
3802 @rtype str | 3955 @rtype str |
3803 """ | 3956 """ |
3804 try: | 3957 try: |
3805 return self.pdata["LICENSE"] | 3958 return self.pdata["LICENSE"] |
3806 except KeyError: | 3959 except KeyError: |
3807 return "" | 3960 return "" |
3808 | 3961 |
3809 def __isInPdata(self, fn): | 3962 def __isInPdata(self, fn): |
3810 """ | 3963 """ |
3811 Private method used to check, if the passed in filename is project | 3964 Private method used to check, if the passed in filename is project |
3812 controlled.. | 3965 controlled.. |
3813 | 3966 |
3814 @param fn filename to be checked | 3967 @param fn filename to be checked |
3815 @type str | 3968 @type str |
3816 @return flag indicating membership | 3969 @return flag indicating membership |
3817 @rtype bool | 3970 @rtype bool |
3818 """ | 3971 """ |
3819 newfn = os.path.abspath(fn) | 3972 newfn = os.path.abspath(fn) |
3820 newfn = self.getRelativePath(newfn) | 3973 newfn = self.getRelativePath(newfn) |
3821 return any( | 3974 return any( |
3822 newfn in self.pdata[group] | 3975 newfn in self.pdata[group] |
3823 for group in [ | 3976 for group in [ |
3824 "SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", "RESOURCES", | 3977 "SOURCES", |
3825 "TRANSLATIONS", "OTHERS" | 3978 "FORMS", |
3979 "INTERFACES", | |
3980 "PROTOCOLS", | |
3981 "RESOURCES", | |
3982 "TRANSLATIONS", | |
3983 "OTHERS", | |
3826 ] | 3984 ] |
3827 ) | 3985 ) |
3828 | 3986 |
3829 def isProjectFile(self, fn): | 3987 def isProjectFile(self, fn): |
3830 """ | 3988 """ |
3831 Public method used to check, if the passed in filename belongs to the | 3989 Public method used to check, if the passed in filename belongs to the |
3832 project. | 3990 project. |
3833 | 3991 |
3834 @param fn filename to be checked (string) | 3992 @param fn filename to be checked (string) |
3835 @return flag indicating membership (boolean) | 3993 @return flag indicating membership (boolean) |
3836 """ | 3994 """ |
3837 return any( | 3995 return any( |
3838 self.__checkProjectFileGroup(fn, group) | 3996 self.__checkProjectFileGroup(fn, group) |
3839 for group in [ | 3997 for group in [ |
3840 "SOURCES", "FORMS", "INTERFACES", "PROTOCOLS", "RESOURCES", | 3998 "SOURCES", |
3841 "TRANSLATIONS", "OTHERS" | 3999 "FORMS", |
4000 "INTERFACES", | |
4001 "PROTOCOLS", | |
4002 "RESOURCES", | |
4003 "TRANSLATIONS", | |
4004 "OTHERS", | |
3842 ] | 4005 ] |
3843 ) | 4006 ) |
3844 | 4007 |
3845 def __checkProjectFileGroup(self, fn, group): | 4008 def __checkProjectFileGroup(self, fn, group): |
3846 """ | 4009 """ |
3847 Private method to check, if a file is in a specific file group of the | 4010 Private method to check, if a file is in a specific file group of the |
3848 project. | 4011 project. |
3849 | 4012 |
3850 @param fn filename to be checked (string) | 4013 @param fn filename to be checked (string) |
3851 @param group group to check (string) | 4014 @param group group to check (string) |
3852 @return flag indicating membership (boolean) | 4015 @return flag indicating membership (boolean) |
3853 """ | 4016 """ |
3854 newfn = os.path.abspath(fn) | 4017 newfn = os.path.abspath(fn) |
3855 newfn = self.getRelativePath(newfn) | 4018 newfn = self.getRelativePath(newfn) |
3856 if ( | 4019 if newfn in self.pdata[group] or ( |
3857 newfn in self.pdata[group] or | 4020 group == "OTHERS" |
3858 (group == "OTHERS" and | 4021 and any(newfn.startswith(entry) for entry in self.pdata[group]) |
3859 any(newfn.startswith(entry) for entry in self.pdata[group])) | |
3860 ): | 4022 ): |
3861 return True | 4023 return True |
3862 | 4024 |
3863 if Utilities.isWindowsPlatform(): | 4025 if Utilities.isWindowsPlatform(): |
3864 # try the above case-insensitive | 4026 # try the above case-insensitive |
3865 newfn = newfn.lower() | 4027 newfn = newfn.lower() |
3866 if any(entry.lower() == newfn for entry in self.pdata[group]): | 4028 if any(entry.lower() == newfn for entry in self.pdata[group]): |
3867 return True | 4029 return True |
3868 elif ( | 4030 elif group == "OTHERS" and any( |
3869 group == "OTHERS" and | 4031 newfn.startswith(entry.lower()) for entry in self.pdata[group] |
3870 any(newfn.startswith(entry.lower()) | |
3871 for entry in self.pdata[group]) | |
3872 ): | 4032 ): |
3873 return True | 4033 return True |
3874 | 4034 |
3875 return False | 4035 return False |
3876 | 4036 |
3877 def isProjectSource(self, fn): | 4037 def isProjectSource(self, fn): |
3878 """ | 4038 """ |
3879 Public method used to check, if the passed in filename belongs to the | 4039 Public method used to check, if the passed in filename belongs to the |
3880 project sources. | 4040 project sources. |
3881 | 4041 |
3882 @param fn filename to be checked (string) | 4042 @param fn filename to be checked (string) |
3883 @return flag indicating membership (boolean) | 4043 @return flag indicating membership (boolean) |
3884 """ | 4044 """ |
3885 return self.__checkProjectFileGroup(fn, "SOURCES") | 4045 return self.__checkProjectFileGroup(fn, "SOURCES") |
3886 | 4046 |
3887 def isProjectForm(self, fn): | 4047 def isProjectForm(self, fn): |
3888 """ | 4048 """ |
3889 Public method used to check, if the passed in filename belongs to the | 4049 Public method used to check, if the passed in filename belongs to the |
3890 project forms. | 4050 project forms. |
3891 | 4051 |
3892 @param fn filename to be checked (string) | 4052 @param fn filename to be checked (string) |
3893 @return flag indicating membership (boolean) | 4053 @return flag indicating membership (boolean) |
3894 """ | 4054 """ |
3895 return self.__checkProjectFileGroup(fn, "FORMS") | 4055 return self.__checkProjectFileGroup(fn, "FORMS") |
3896 | 4056 |
3897 def isProjectInterface(self, fn): | 4057 def isProjectInterface(self, fn): |
3898 """ | 4058 """ |
3899 Public method used to check, if the passed in filename belongs to the | 4059 Public method used to check, if the passed in filename belongs to the |
3900 project interfaces. | 4060 project interfaces. |
3901 | 4061 |
3902 @param fn filename to be checked (string) | 4062 @param fn filename to be checked (string) |
3903 @return flag indicating membership (boolean) | 4063 @return flag indicating membership (boolean) |
3904 """ | 4064 """ |
3905 return self.__checkProjectFileGroup(fn, "INTERFACES") | 4065 return self.__checkProjectFileGroup(fn, "INTERFACES") |
3906 | 4066 |
3907 def isProjectProtocol(self, fn): | 4067 def isProjectProtocol(self, fn): |
3908 """ | 4068 """ |
3909 Public method used to check, if the passed in filename belongs to the | 4069 Public method used to check, if the passed in filename belongs to the |
3910 project protocols. | 4070 project protocols. |
3911 | 4071 |
3912 @param fn filename to be checked | 4072 @param fn filename to be checked |
3913 @type str | 4073 @type str |
3914 @return flag indicating membership | 4074 @return flag indicating membership |
3915 @rtype bool | 4075 @rtype bool |
3916 """ | 4076 """ |
3917 return self.__checkProjectFileGroup(fn, "PROTOCOLS") | 4077 return self.__checkProjectFileGroup(fn, "PROTOCOLS") |
3918 | 4078 |
3919 def isProjectResource(self, fn): | 4079 def isProjectResource(self, fn): |
3920 """ | 4080 """ |
3921 Public method used to check, if the passed in filename belongs to the | 4081 Public method used to check, if the passed in filename belongs to the |
3922 project resources. | 4082 project resources. |
3923 | 4083 |
3924 @param fn filename to be checked (string) | 4084 @param fn filename to be checked (string) |
3925 @return flag indicating membership (boolean) | 4085 @return flag indicating membership (boolean) |
3926 """ | 4086 """ |
3927 return self.__checkProjectFileGroup(fn, "RESOURCES") | 4087 return self.__checkProjectFileGroup(fn, "RESOURCES") |
3928 | 4088 |
3929 def initActions(self): | 4089 def initActions(self): |
3930 """ | 4090 """ |
3931 Public slot to initialize the project related actions. | 4091 Public slot to initialize the project related actions. |
3932 """ | 4092 """ |
3933 self.actions = [] | 4093 self.actions = [] |
3934 | 4094 |
3935 ################################################################### | 4095 ################################################################### |
3936 ## Project actions | 4096 ## Project actions |
3937 ################################################################### | 4097 ################################################################### |
3938 | 4098 |
3939 self.actGrp1 = createActionGroup(self) | 4099 self.actGrp1 = createActionGroup(self) |
3940 | 4100 |
3941 act = EricAction( | 4101 act = EricAction( |
3942 self.tr('New project'), | 4102 self.tr("New project"), |
3943 UI.PixmapCache.getIcon("projectNew"), | 4103 UI.PixmapCache.getIcon("projectNew"), |
3944 self.tr('&New...'), 0, 0, | 4104 self.tr("&New..."), |
3945 self.actGrp1, 'project_new') | 4105 0, |
3946 act.setStatusTip(self.tr('Generate a new project')) | 4106 0, |
3947 act.setWhatsThis(self.tr( | 4107 self.actGrp1, |
3948 """<b>New...</b>""" | 4108 "project_new", |
3949 """<p>This opens a dialog for entering the info for a""" | 4109 ) |
3950 """ new project.</p>""" | 4110 act.setStatusTip(self.tr("Generate a new project")) |
3951 )) | 4111 act.setWhatsThis( |
4112 self.tr( | |
4113 """<b>New...</b>""" | |
4114 """<p>This opens a dialog for entering the info for a""" | |
4115 """ new project.</p>""" | |
4116 ) | |
4117 ) | |
3952 act.triggered.connect(self.createNewProject) | 4118 act.triggered.connect(self.createNewProject) |
3953 self.actions.append(act) | 4119 self.actions.append(act) |
3954 | 4120 |
3955 act = EricAction( | 4121 act = EricAction( |
3956 self.tr('Open project'), | 4122 self.tr("Open project"), |
3957 UI.PixmapCache.getIcon("projectOpen"), | 4123 UI.PixmapCache.getIcon("projectOpen"), |
3958 self.tr('&Open...'), 0, 0, | 4124 self.tr("&Open..."), |
3959 self.actGrp1, 'project_open') | 4125 0, |
3960 act.setStatusTip(self.tr('Open an existing project')) | 4126 0, |
3961 act.setWhatsThis(self.tr( | 4127 self.actGrp1, |
3962 """<b>Open...</b>""" | 4128 "project_open", |
3963 """<p>This opens an existing project.</p>""" | 4129 ) |
3964 )) | 4130 act.setStatusTip(self.tr("Open an existing project")) |
4131 act.setWhatsThis( | |
4132 self.tr("""<b>Open...</b>""" """<p>This opens an existing project.</p>""") | |
4133 ) | |
3965 act.triggered.connect(self.openProject) | 4134 act.triggered.connect(self.openProject) |
3966 self.actions.append(act) | 4135 self.actions.append(act) |
3967 | 4136 |
3968 self.closeAct = EricAction( | 4137 self.closeAct = EricAction( |
3969 self.tr('Close project'), | 4138 self.tr("Close project"), |
3970 UI.PixmapCache.getIcon("projectClose"), | 4139 UI.PixmapCache.getIcon("projectClose"), |
3971 self.tr('&Close'), 0, 0, self, 'project_close') | 4140 self.tr("&Close"), |
3972 self.closeAct.setStatusTip(self.tr('Close the current project')) | 4141 0, |
3973 self.closeAct.setWhatsThis(self.tr( | 4142 0, |
3974 """<b>Close</b>""" | 4143 self, |
3975 """<p>This closes the current project.</p>""" | 4144 "project_close", |
3976 )) | 4145 ) |
4146 self.closeAct.setStatusTip(self.tr("Close the current project")) | |
4147 self.closeAct.setWhatsThis( | |
4148 self.tr("""<b>Close</b>""" """<p>This closes the current project.</p>""") | |
4149 ) | |
3977 self.closeAct.triggered.connect(self.closeProject) | 4150 self.closeAct.triggered.connect(self.closeProject) |
3978 self.actions.append(self.closeAct) | 4151 self.actions.append(self.closeAct) |
3979 | 4152 |
3980 self.saveAct = EricAction( | 4153 self.saveAct = EricAction( |
3981 self.tr('Save project'), | 4154 self.tr("Save project"), |
3982 UI.PixmapCache.getIcon("projectSave"), | 4155 UI.PixmapCache.getIcon("projectSave"), |
3983 self.tr('&Save'), 0, 0, self, 'project_save') | 4156 self.tr("&Save"), |
3984 self.saveAct.setStatusTip(self.tr('Save the current project')) | 4157 0, |
3985 self.saveAct.setWhatsThis(self.tr( | 4158 0, |
3986 """<b>Save</b>""" | 4159 self, |
3987 """<p>This saves the current project.</p>""" | 4160 "project_save", |
3988 )) | 4161 ) |
4162 self.saveAct.setStatusTip(self.tr("Save the current project")) | |
4163 self.saveAct.setWhatsThis( | |
4164 self.tr("""<b>Save</b>""" """<p>This saves the current project.</p>""") | |
4165 ) | |
3989 self.saveAct.triggered.connect(self.saveProject) | 4166 self.saveAct.triggered.connect(self.saveProject) |
3990 self.actions.append(self.saveAct) | 4167 self.actions.append(self.saveAct) |
3991 | 4168 |
3992 self.saveasAct = EricAction( | 4169 self.saveasAct = EricAction( |
3993 self.tr('Save project as'), | 4170 self.tr("Save project as"), |
3994 UI.PixmapCache.getIcon("projectSaveAs"), | 4171 UI.PixmapCache.getIcon("projectSaveAs"), |
3995 self.tr('Save &as...'), 0, 0, self, 'project_save_as') | 4172 self.tr("Save &as..."), |
3996 self.saveasAct.setStatusTip(self.tr( | 4173 0, |
3997 'Save the current project to a new file')) | 4174 0, |
3998 self.saveasAct.setWhatsThis(self.tr( | 4175 self, |
3999 """<b>Save as</b>""" | 4176 "project_save_as", |
4000 """<p>This saves the current project to a new file.</p>""" | 4177 ) |
4001 )) | 4178 self.saveasAct.setStatusTip(self.tr("Save the current project to a new file")) |
4179 self.saveasAct.setWhatsThis( | |
4180 self.tr( | |
4181 """<b>Save as</b>""" | |
4182 """<p>This saves the current project to a new file.</p>""" | |
4183 ) | |
4184 ) | |
4002 self.saveasAct.triggered.connect(self.saveProjectAs) | 4185 self.saveasAct.triggered.connect(self.saveProjectAs) |
4003 self.actions.append(self.saveasAct) | 4186 self.actions.append(self.saveasAct) |
4004 | 4187 |
4005 ################################################################### | 4188 ################################################################### |
4006 ## Project management actions | 4189 ## Project management actions |
4007 ################################################################### | 4190 ################################################################### |
4008 | 4191 |
4009 self.actGrp2 = createActionGroup(self) | 4192 self.actGrp2 = createActionGroup(self) |
4010 | 4193 |
4011 self.addFilesAct = EricAction( | 4194 self.addFilesAct = EricAction( |
4012 self.tr('Add files to project'), | 4195 self.tr("Add files to project"), |
4013 UI.PixmapCache.getIcon("fileMisc"), | 4196 UI.PixmapCache.getIcon("fileMisc"), |
4014 self.tr('Add &files...'), 0, 0, | 4197 self.tr("Add &files..."), |
4015 self.actGrp2, 'project_add_file') | 4198 0, |
4016 self.addFilesAct.setStatusTip(self.tr( | 4199 0, |
4017 'Add files to the current project')) | 4200 self.actGrp2, |
4018 self.addFilesAct.setWhatsThis(self.tr( | 4201 "project_add_file", |
4019 """<b>Add files...</b>""" | 4202 ) |
4020 """<p>This opens a dialog for adding files""" | 4203 self.addFilesAct.setStatusTip(self.tr("Add files to the current project")) |
4021 """ to the current project. The place to add is""" | 4204 self.addFilesAct.setWhatsThis( |
4022 """ determined by the file extension.</p>""" | 4205 self.tr( |
4023 )) | 4206 """<b>Add files...</b>""" |
4207 """<p>This opens a dialog for adding files""" | |
4208 """ to the current project. The place to add is""" | |
4209 """ determined by the file extension.</p>""" | |
4210 ) | |
4211 ) | |
4024 self.addFilesAct.triggered.connect(self.addFiles) | 4212 self.addFilesAct.triggered.connect(self.addFiles) |
4025 self.actions.append(self.addFilesAct) | 4213 self.actions.append(self.addFilesAct) |
4026 | 4214 |
4027 self.addDirectoryAct = EricAction( | 4215 self.addDirectoryAct = EricAction( |
4028 self.tr('Add directory to project'), | 4216 self.tr("Add directory to project"), |
4029 UI.PixmapCache.getIcon("dirOpen"), | 4217 UI.PixmapCache.getIcon("dirOpen"), |
4030 self.tr('Add directory...'), 0, 0, | 4218 self.tr("Add directory..."), |
4031 self.actGrp2, 'project_add_directory') | 4219 0, |
4220 0, | |
4221 self.actGrp2, | |
4222 "project_add_directory", | |
4223 ) | |
4032 self.addDirectoryAct.setStatusTip( | 4224 self.addDirectoryAct.setStatusTip( |
4033 self.tr('Add a directory to the current project')) | 4225 self.tr("Add a directory to the current project") |
4034 self.addDirectoryAct.setWhatsThis(self.tr( | 4226 ) |
4035 """<b>Add directory...</b>""" | 4227 self.addDirectoryAct.setWhatsThis( |
4036 """<p>This opens a dialog for adding a directory""" | 4228 self.tr( |
4037 """ to the current project.</p>""" | 4229 """<b>Add directory...</b>""" |
4038 )) | 4230 """<p>This opens a dialog for adding a directory""" |
4231 """ to the current project.</p>""" | |
4232 ) | |
4233 ) | |
4039 self.addDirectoryAct.triggered.connect(self.addDirectory) | 4234 self.addDirectoryAct.triggered.connect(self.addDirectory) |
4040 self.actions.append(self.addDirectoryAct) | 4235 self.actions.append(self.addDirectoryAct) |
4041 | 4236 |
4042 self.addLanguageAct = EricAction( | 4237 self.addLanguageAct = EricAction( |
4043 self.tr('Add translation to project'), | 4238 self.tr("Add translation to project"), |
4044 UI.PixmapCache.getIcon("linguist4"), | 4239 UI.PixmapCache.getIcon("linguist4"), |
4045 self.tr('Add &translation...'), 0, 0, | 4240 self.tr("Add &translation..."), |
4046 self.actGrp2, 'project_add_translation') | 4241 0, |
4242 0, | |
4243 self.actGrp2, | |
4244 "project_add_translation", | |
4245 ) | |
4047 self.addLanguageAct.setStatusTip( | 4246 self.addLanguageAct.setStatusTip( |
4048 self.tr('Add a translation to the current project')) | 4247 self.tr("Add a translation to the current project") |
4049 self.addLanguageAct.setWhatsThis(self.tr( | 4248 ) |
4050 """<b>Add translation...</b>""" | 4249 self.addLanguageAct.setWhatsThis( |
4051 """<p>This opens a dialog for add a translation""" | 4250 self.tr( |
4052 """ to the current project.</p>""" | 4251 """<b>Add translation...</b>""" |
4053 )) | 4252 """<p>This opens a dialog for add a translation""" |
4253 """ to the current project.</p>""" | |
4254 ) | |
4255 ) | |
4054 self.addLanguageAct.triggered.connect(self.addLanguage) | 4256 self.addLanguageAct.triggered.connect(self.addLanguage) |
4055 self.actions.append(self.addLanguageAct) | 4257 self.actions.append(self.addLanguageAct) |
4056 | 4258 |
4057 act = EricAction( | 4259 act = EricAction( |
4058 self.tr('Search new files'), | 4260 self.tr("Search new files"), |
4059 self.tr('Searc&h new files...'), 0, 0, | 4261 self.tr("Searc&h new files..."), |
4060 self.actGrp2, 'project_search_new_files') | 4262 0, |
4061 act.setStatusTip(self.tr( | 4263 0, |
4062 'Search new files in the project directory.')) | 4264 self.actGrp2, |
4063 act.setWhatsThis(self.tr( | 4265 "project_search_new_files", |
4064 """<b>Search new files...</b>""" | 4266 ) |
4065 """<p>This searches for new files (sources, *.ui, *.idl,""" | 4267 act.setStatusTip(self.tr("Search new files in the project directory.")) |
4066 """ *.proto) in the project directory and registered""" | 4268 act.setWhatsThis( |
4067 """ subdirectories.</p>""" | 4269 self.tr( |
4068 )) | 4270 """<b>Search new files...</b>""" |
4271 """<p>This searches for new files (sources, *.ui, *.idl,""" | |
4272 """ *.proto) in the project directory and registered""" | |
4273 """ subdirectories.</p>""" | |
4274 ) | |
4275 ) | |
4069 act.triggered.connect(self.__searchNewFiles) | 4276 act.triggered.connect(self.__searchNewFiles) |
4070 self.actions.append(act) | 4277 self.actions.append(act) |
4071 | 4278 |
4072 act = EricAction( | 4279 act = EricAction( |
4073 self.tr('Search Project File'), | 4280 self.tr("Search Project File"), |
4074 self.tr('Search Project File...'), | 4281 self.tr("Search Project File..."), |
4075 QKeySequence(self.tr("Alt+Ctrl+P", "Project|Search Project File")), | 4282 QKeySequence(self.tr("Alt+Ctrl+P", "Project|Search Project File")), |
4076 0, | 4283 0, |
4077 self.actGrp2, 'project_search_project_file') | 4284 self.actGrp2, |
4078 act.setStatusTip(self.tr( | 4285 "project_search_project_file", |
4079 'Search for a file in the project list of files.')) | 4286 ) |
4080 act.setWhatsThis(self.tr( | 4287 act.setStatusTip(self.tr("Search for a file in the project list of files.")) |
4081 """<b>Search Project File</b>""" | 4288 act.setWhatsThis( |
4082 """<p>This searches for a file in the project list of files.</p>""" | 4289 self.tr( |
4083 )) | 4290 """<b>Search Project File</b>""" |
4291 """<p>This searches for a file in the project list of files.</p>""" | |
4292 ) | |
4293 ) | |
4084 act.triggered.connect(self.__searchProjectFile) | 4294 act.triggered.connect(self.__searchProjectFile) |
4085 self.actions.append(act) | 4295 self.actions.append(act) |
4086 | 4296 |
4087 self.propsAct = EricAction( | 4297 self.propsAct = EricAction( |
4088 self.tr('Project properties'), | 4298 self.tr("Project properties"), |
4089 UI.PixmapCache.getIcon("projectProps"), | 4299 UI.PixmapCache.getIcon("projectProps"), |
4090 self.tr('&Properties...'), 0, 0, self, | 4300 self.tr("&Properties..."), |
4091 'project_properties') | 4301 0, |
4092 self.propsAct.setStatusTip(self.tr('Show the project properties')) | 4302 0, |
4093 self.propsAct.setWhatsThis(self.tr( | 4303 self, |
4094 """<b>Properties...</b>""" | 4304 "project_properties", |
4095 """<p>This shows a dialog to edit the project properties.</p>""" | 4305 ) |
4096 )) | 4306 self.propsAct.setStatusTip(self.tr("Show the project properties")) |
4307 self.propsAct.setWhatsThis( | |
4308 self.tr( | |
4309 """<b>Properties...</b>""" | |
4310 """<p>This shows a dialog to edit the project properties.</p>""" | |
4311 ) | |
4312 ) | |
4097 self.propsAct.triggered.connect(self.__showProperties) | 4313 self.propsAct.triggered.connect(self.__showProperties) |
4098 self.actions.append(self.propsAct) | 4314 self.actions.append(self.propsAct) |
4099 | 4315 |
4100 self.userPropsAct = EricAction( | 4316 self.userPropsAct = EricAction( |
4101 self.tr('User project properties'), | 4317 self.tr("User project properties"), |
4102 UI.PixmapCache.getIcon("projectUserProps"), | 4318 UI.PixmapCache.getIcon("projectUserProps"), |
4103 self.tr('&User Properties...'), 0, 0, self, | 4319 self.tr("&User Properties..."), |
4104 'project_user_properties') | 4320 0, |
4105 self.userPropsAct.setStatusTip(self.tr( | 4321 0, |
4106 'Show the user specific project properties')) | 4322 self, |
4107 self.userPropsAct.setWhatsThis(self.tr( | 4323 "project_user_properties", |
4108 """<b>User Properties...</b>""" | 4324 ) |
4109 """<p>This shows a dialog to edit the user specific project""" | 4325 self.userPropsAct.setStatusTip( |
4110 """ properties.</p>""" | 4326 self.tr("Show the user specific project properties") |
4111 )) | 4327 ) |
4328 self.userPropsAct.setWhatsThis( | |
4329 self.tr( | |
4330 """<b>User Properties...</b>""" | |
4331 """<p>This shows a dialog to edit the user specific project""" | |
4332 """ properties.</p>""" | |
4333 ) | |
4334 ) | |
4112 self.userPropsAct.triggered.connect(self.__showUserProperties) | 4335 self.userPropsAct.triggered.connect(self.__showUserProperties) |
4113 self.actions.append(self.userPropsAct) | 4336 self.actions.append(self.userPropsAct) |
4114 | 4337 |
4115 self.filetypesAct = EricAction( | 4338 self.filetypesAct = EricAction( |
4116 self.tr('Filetype Associations'), | 4339 self.tr("Filetype Associations"), |
4117 self.tr('Filetype Associations...'), 0, 0, | 4340 self.tr("Filetype Associations..."), |
4118 self, 'project_filetype_associations') | 4341 0, |
4342 0, | |
4343 self, | |
4344 "project_filetype_associations", | |
4345 ) | |
4119 self.filetypesAct.setStatusTip( | 4346 self.filetypesAct.setStatusTip( |
4120 self.tr('Show the project file type associations')) | 4347 self.tr("Show the project file type associations") |
4121 self.filetypesAct.setWhatsThis(self.tr( | 4348 ) |
4122 """<b>Filetype Associations...</b>""" | 4349 self.filetypesAct.setWhatsThis( |
4123 """<p>This shows a dialog to edit the file type associations of""" | 4350 self.tr( |
4124 """ the project. These associations determine the type""" | 4351 """<b>Filetype Associations...</b>""" |
4125 """ (source, form, interface, protocol or others) with a""" | 4352 """<p>This shows a dialog to edit the file type associations of""" |
4126 """ filename pattern. They are used when adding a file to the""" | 4353 """ the project. These associations determine the type""" |
4127 """ project and when performing a search for new files.</p>""" | 4354 """ (source, form, interface, protocol or others) with a""" |
4128 )) | 4355 """ filename pattern. They are used when adding a file to the""" |
4129 self.filetypesAct.triggered.connect( | 4356 """ project and when performing a search for new files.</p>""" |
4130 self.__showFiletypeAssociations) | 4357 ) |
4358 ) | |
4359 self.filetypesAct.triggered.connect(self.__showFiletypeAssociations) | |
4131 self.actions.append(self.filetypesAct) | 4360 self.actions.append(self.filetypesAct) |
4132 | 4361 |
4133 self.lexersAct = EricAction( | 4362 self.lexersAct = EricAction( |
4134 self.tr('Lexer Associations'), | 4363 self.tr("Lexer Associations"), |
4135 self.tr('Lexer Associations...'), 0, 0, | 4364 self.tr("Lexer Associations..."), |
4136 self, 'project_lexer_associations') | 4365 0, |
4137 self.lexersAct.setStatusTip(self.tr( | 4366 0, |
4138 'Show the project lexer associations (overriding defaults)')) | 4367 self, |
4139 self.lexersAct.setWhatsThis(self.tr( | 4368 "project_lexer_associations", |
4140 """<b>Lexer Associations...</b>""" | 4369 ) |
4141 """<p>This shows a dialog to edit the lexer associations of""" | 4370 self.lexersAct.setStatusTip( |
4142 """ the project. These associations override the global lexer""" | 4371 self.tr("Show the project lexer associations (overriding defaults)") |
4143 """ associations. Lexers are used to highlight the editor""" | 4372 ) |
4144 """ text.</p>""" | 4373 self.lexersAct.setWhatsThis( |
4145 )) | 4374 self.tr( |
4375 """<b>Lexer Associations...</b>""" | |
4376 """<p>This shows a dialog to edit the lexer associations of""" | |
4377 """ the project. These associations override the global lexer""" | |
4378 """ associations. Lexers are used to highlight the editor""" | |
4379 """ text.</p>""" | |
4380 ) | |
4381 ) | |
4146 self.lexersAct.triggered.connect(self.__showLexerAssociations) | 4382 self.lexersAct.triggered.connect(self.__showLexerAssociations) |
4147 self.actions.append(self.lexersAct) | 4383 self.actions.append(self.lexersAct) |
4148 | 4384 |
4149 ################################################################### | 4385 ################################################################### |
4150 ## Project debug actions | 4386 ## Project debug actions |
4151 ################################################################### | 4387 ################################################################### |
4152 | 4388 |
4153 self.dbgActGrp = createActionGroup(self) | 4389 self.dbgActGrp = createActionGroup(self) |
4154 | 4390 |
4155 act = EricAction( | 4391 act = EricAction( |
4156 self.tr('Debugger Properties'), | 4392 self.tr("Debugger Properties"), |
4157 self.tr('Debugger &Properties...'), 0, 0, | 4393 self.tr("Debugger &Properties..."), |
4158 self.dbgActGrp, 'project_debugger_properties') | 4394 0, |
4159 act.setStatusTip(self.tr('Show the debugger properties')) | 4395 0, |
4160 act.setWhatsThis(self.tr( | 4396 self.dbgActGrp, |
4161 """<b>Debugger Properties...</b>""" | 4397 "project_debugger_properties", |
4162 """<p>This shows a dialog to edit project specific debugger""" | 4398 ) |
4163 """ settings.</p>""" | 4399 act.setStatusTip(self.tr("Show the debugger properties")) |
4164 )) | 4400 act.setWhatsThis( |
4401 self.tr( | |
4402 """<b>Debugger Properties...</b>""" | |
4403 """<p>This shows a dialog to edit project specific debugger""" | |
4404 """ settings.</p>""" | |
4405 ) | |
4406 ) | |
4165 act.triggered.connect(self.__showDebugProperties) | 4407 act.triggered.connect(self.__showDebugProperties) |
4166 self.actions.append(act) | 4408 self.actions.append(act) |
4167 | 4409 |
4168 act = EricAction( | 4410 act = EricAction( |
4169 self.tr('Load'), | 4411 self.tr("Load"), |
4170 self.tr('&Load'), 0, 0, | 4412 self.tr("&Load"), |
4171 self.dbgActGrp, 'project_debugger_properties_load') | 4413 0, |
4172 act.setStatusTip(self.tr('Load the debugger properties')) | 4414 0, |
4173 act.setWhatsThis(self.tr( | 4415 self.dbgActGrp, |
4174 """<b>Load Debugger Properties</b>""" | 4416 "project_debugger_properties_load", |
4175 """<p>This loads the project specific debugger settings.</p>""" | 4417 ) |
4176 )) | 4418 act.setStatusTip(self.tr("Load the debugger properties")) |
4419 act.setWhatsThis( | |
4420 self.tr( | |
4421 """<b>Load Debugger Properties</b>""" | |
4422 """<p>This loads the project specific debugger settings.</p>""" | |
4423 ) | |
4424 ) | |
4177 act.triggered.connect(self.__readDebugProperties) | 4425 act.triggered.connect(self.__readDebugProperties) |
4178 self.actions.append(act) | 4426 self.actions.append(act) |
4179 | 4427 |
4180 act = EricAction( | 4428 act = EricAction( |
4181 self.tr('Save'), | 4429 self.tr("Save"), |
4182 self.tr('&Save'), 0, 0, | 4430 self.tr("&Save"), |
4183 self.dbgActGrp, 'project_debugger_properties_save') | 4431 0, |
4184 act.setStatusTip(self.tr('Save the debugger properties')) | 4432 0, |
4185 act.setWhatsThis(self.tr( | 4433 self.dbgActGrp, |
4186 """<b>Save Debugger Properties</b>""" | 4434 "project_debugger_properties_save", |
4187 """<p>This saves the project specific debugger settings.</p>""" | 4435 ) |
4188 )) | 4436 act.setStatusTip(self.tr("Save the debugger properties")) |
4437 act.setWhatsThis( | |
4438 self.tr( | |
4439 """<b>Save Debugger Properties</b>""" | |
4440 """<p>This saves the project specific debugger settings.</p>""" | |
4441 ) | |
4442 ) | |
4189 act.triggered.connect(self.__writeDebugProperties) | 4443 act.triggered.connect(self.__writeDebugProperties) |
4190 self.actions.append(act) | 4444 self.actions.append(act) |
4191 | 4445 |
4192 act = EricAction( | 4446 act = EricAction( |
4193 self.tr('Delete'), | 4447 self.tr("Delete"), |
4194 self.tr('&Delete'), 0, 0, | 4448 self.tr("&Delete"), |
4195 self.dbgActGrp, 'project_debugger_properties_delete') | 4449 0, |
4196 act.setStatusTip(self.tr('Delete the debugger properties')) | 4450 0, |
4197 act.setWhatsThis(self.tr( | 4451 self.dbgActGrp, |
4198 """<b>Delete Debugger Properties</b>""" | 4452 "project_debugger_properties_delete", |
4199 """<p>This deletes the file containing the project specific""" | 4453 ) |
4200 """ debugger settings.</p>""" | 4454 act.setStatusTip(self.tr("Delete the debugger properties")) |
4201 )) | 4455 act.setWhatsThis( |
4456 self.tr( | |
4457 """<b>Delete Debugger Properties</b>""" | |
4458 """<p>This deletes the file containing the project specific""" | |
4459 """ debugger settings.</p>""" | |
4460 ) | |
4461 ) | |
4202 act.triggered.connect(self.__deleteDebugProperties) | 4462 act.triggered.connect(self.__deleteDebugProperties) |
4203 self.actions.append(act) | 4463 self.actions.append(act) |
4204 | 4464 |
4205 act = EricAction( | 4465 act = EricAction( |
4206 self.tr('Reset'), | 4466 self.tr("Reset"), |
4207 self.tr('&Reset'), 0, 0, | 4467 self.tr("&Reset"), |
4208 self.dbgActGrp, 'project_debugger_properties_resets') | 4468 0, |
4209 act.setStatusTip(self.tr('Reset the debugger properties')) | 4469 0, |
4210 act.setWhatsThis(self.tr( | 4470 self.dbgActGrp, |
4211 """<b>Reset Debugger Properties</b>""" | 4471 "project_debugger_properties_resets", |
4212 """<p>This resets the project specific debugger settings.</p>""" | 4472 ) |
4213 )) | 4473 act.setStatusTip(self.tr("Reset the debugger properties")) |
4474 act.setWhatsThis( | |
4475 self.tr( | |
4476 """<b>Reset Debugger Properties</b>""" | |
4477 """<p>This resets the project specific debugger settings.</p>""" | |
4478 ) | |
4479 ) | |
4214 act.triggered.connect(self.__initDebugProperties) | 4480 act.triggered.connect(self.__initDebugProperties) |
4215 self.actions.append(act) | 4481 self.actions.append(act) |
4216 | 4482 |
4217 ################################################################### | 4483 ################################################################### |
4218 ## Project session actions | 4484 ## Project session actions |
4219 ################################################################### | 4485 ################################################################### |
4220 | 4486 |
4221 self.sessActGrp = createActionGroup(self) | 4487 self.sessActGrp = createActionGroup(self) |
4222 | 4488 |
4223 act = EricAction( | 4489 act = EricAction( |
4224 self.tr('Load session'), | 4490 self.tr("Load session"), |
4225 self.tr('Load session'), 0, 0, | 4491 self.tr("Load session"), |
4226 self.sessActGrp, 'project_load_session') | 4492 0, |
4227 act.setStatusTip(self.tr('Load the projects session file.')) | 4493 0, |
4228 act.setWhatsThis(self.tr( | 4494 self.sessActGrp, |
4229 """<b>Load session</b>""" | 4495 "project_load_session", |
4230 """<p>This loads the projects session file. The session consists""" | 4496 ) |
4231 """ of the following data.<br>""" | 4497 act.setStatusTip(self.tr("Load the projects session file.")) |
4232 """- all open source files<br>""" | 4498 act.setWhatsThis( |
4233 """- all breakpoint<br>""" | 4499 self.tr( |
4234 """- the commandline arguments<br>""" | 4500 """<b>Load session</b>""" |
4235 """- the working directory<br>""" | 4501 """<p>This loads the projects session file. The session consists""" |
4236 """- the exception reporting flag</p>""" | 4502 """ of the following data.<br>""" |
4237 )) | 4503 """- all open source files<br>""" |
4504 """- all breakpoint<br>""" | |
4505 """- the commandline arguments<br>""" | |
4506 """- the working directory<br>""" | |
4507 """- the exception reporting flag</p>""" | |
4508 ) | |
4509 ) | |
4238 act.triggered.connect(self.__readSession) | 4510 act.triggered.connect(self.__readSession) |
4239 self.actions.append(act) | 4511 self.actions.append(act) |
4240 | 4512 |
4241 act = EricAction( | 4513 act = EricAction( |
4242 self.tr('Save session'), | 4514 self.tr("Save session"), |
4243 self.tr('Save session'), 0, 0, | 4515 self.tr("Save session"), |
4244 self.sessActGrp, 'project_save_session') | 4516 0, |
4245 act.setStatusTip(self.tr('Save the projects session file.')) | 4517 0, |
4246 act.setWhatsThis(self.tr( | 4518 self.sessActGrp, |
4247 """<b>Save session</b>""" | 4519 "project_save_session", |
4248 """<p>This saves the projects session file. The session consists""" | 4520 ) |
4249 """ of the following data.<br>""" | 4521 act.setStatusTip(self.tr("Save the projects session file.")) |
4250 """- all open source files<br>""" | 4522 act.setWhatsThis( |
4251 """- all breakpoint<br>""" | 4523 self.tr( |
4252 """- the commandline arguments<br>""" | 4524 """<b>Save session</b>""" |
4253 """- the working directory<br>""" | 4525 """<p>This saves the projects session file. The session consists""" |
4254 """- the exception reporting flag</p>""" | 4526 """ of the following data.<br>""" |
4255 )) | 4527 """- all open source files<br>""" |
4528 """- all breakpoint<br>""" | |
4529 """- the commandline arguments<br>""" | |
4530 """- the working directory<br>""" | |
4531 """- the exception reporting flag</p>""" | |
4532 ) | |
4533 ) | |
4256 act.triggered.connect(self.__writeSession) | 4534 act.triggered.connect(self.__writeSession) |
4257 self.actions.append(act) | 4535 self.actions.append(act) |
4258 | 4536 |
4259 act = EricAction( | 4537 act = EricAction( |
4260 self.tr('Delete session'), | 4538 self.tr("Delete session"), |
4261 self.tr('Delete session'), 0, 0, | 4539 self.tr("Delete session"), |
4262 self.sessActGrp, 'project_delete_session') | 4540 0, |
4263 act.setStatusTip(self.tr('Delete the projects session file.')) | 4541 0, |
4264 act.setWhatsThis(self.tr( | 4542 self.sessActGrp, |
4265 """<b>Delete session</b>""" | 4543 "project_delete_session", |
4266 """<p>This deletes the projects session file</p>""" | 4544 ) |
4267 )) | 4545 act.setStatusTip(self.tr("Delete the projects session file.")) |
4546 act.setWhatsThis( | |
4547 self.tr( | |
4548 """<b>Delete session</b>""" | |
4549 """<p>This deletes the projects session file</p>""" | |
4550 ) | |
4551 ) | |
4268 act.triggered.connect(self.__deleteSession) | 4552 act.triggered.connect(self.__deleteSession) |
4269 self.actions.append(act) | 4553 self.actions.append(act) |
4270 | 4554 |
4271 ################################################################### | 4555 ################################################################### |
4272 ## Project Tools - check actions | 4556 ## Project Tools - check actions |
4273 ################################################################### | 4557 ################################################################### |
4274 | 4558 |
4275 self.chkGrp = createActionGroup(self) | 4559 self.chkGrp = createActionGroup(self) |
4276 | 4560 |
4277 self.codeMetricsAct = EricAction( | 4561 self.codeMetricsAct = EricAction( |
4278 self.tr('Code Metrics'), | 4562 self.tr("Code Metrics"), |
4279 self.tr('&Code Metrics...'), 0, 0, | 4563 self.tr("&Code Metrics..."), |
4280 self.chkGrp, 'project_code_metrics') | 4564 0, |
4565 0, | |
4566 self.chkGrp, | |
4567 "project_code_metrics", | |
4568 ) | |
4281 self.codeMetricsAct.setStatusTip( | 4569 self.codeMetricsAct.setStatusTip( |
4282 self.tr('Show some code metrics for the project.')) | 4570 self.tr("Show some code metrics for the project.") |
4283 self.codeMetricsAct.setWhatsThis(self.tr( | 4571 ) |
4284 """<b>Code Metrics...</b>""" | 4572 self.codeMetricsAct.setWhatsThis( |
4285 """<p>This shows some code metrics for all Python files in""" | 4573 self.tr( |
4286 """ the project.</p>""" | 4574 """<b>Code Metrics...</b>""" |
4287 )) | 4575 """<p>This shows some code metrics for all Python files in""" |
4576 """ the project.</p>""" | |
4577 ) | |
4578 ) | |
4288 self.codeMetricsAct.triggered.connect(self.__showCodeMetrics) | 4579 self.codeMetricsAct.triggered.connect(self.__showCodeMetrics) |
4289 self.actions.append(self.codeMetricsAct) | 4580 self.actions.append(self.codeMetricsAct) |
4290 | 4581 |
4291 self.codeCoverageAct = EricAction( | 4582 self.codeCoverageAct = EricAction( |
4292 self.tr('Python Code Coverage'), | 4583 self.tr("Python Code Coverage"), |
4293 self.tr('Code Co&verage...'), 0, 0, | 4584 self.tr("Code Co&verage..."), |
4294 self.chkGrp, 'project_code_coverage') | 4585 0, |
4586 0, | |
4587 self.chkGrp, | |
4588 "project_code_coverage", | |
4589 ) | |
4295 self.codeCoverageAct.setStatusTip( | 4590 self.codeCoverageAct.setStatusTip( |
4296 self.tr('Show code coverage information for the project.')) | 4591 self.tr("Show code coverage information for the project.") |
4297 self.codeCoverageAct.setWhatsThis(self.tr( | 4592 ) |
4298 """<b>Code Coverage...</b>""" | 4593 self.codeCoverageAct.setWhatsThis( |
4299 """<p>This shows the code coverage information for all Python""" | 4594 self.tr( |
4300 """ files in the project.</p>""" | 4595 """<b>Code Coverage...</b>""" |
4301 )) | 4596 """<p>This shows the code coverage information for all Python""" |
4597 """ files in the project.</p>""" | |
4598 ) | |
4599 ) | |
4302 self.codeCoverageAct.triggered.connect(self.__showCodeCoverage) | 4600 self.codeCoverageAct.triggered.connect(self.__showCodeCoverage) |
4303 self.actions.append(self.codeCoverageAct) | 4601 self.actions.append(self.codeCoverageAct) |
4304 | 4602 |
4305 self.codeProfileAct = EricAction( | 4603 self.codeProfileAct = EricAction( |
4306 self.tr('Profile Data'), | 4604 self.tr("Profile Data"), |
4307 self.tr('&Profile Data...'), 0, 0, | 4605 self.tr("&Profile Data..."), |
4308 self.chkGrp, 'project_profile_data') | 4606 0, |
4607 0, | |
4608 self.chkGrp, | |
4609 "project_profile_data", | |
4610 ) | |
4309 self.codeProfileAct.setStatusTip( | 4611 self.codeProfileAct.setStatusTip( |
4310 self.tr('Show profiling data for the project.')) | 4612 self.tr("Show profiling data for the project.") |
4311 self.codeProfileAct.setWhatsThis(self.tr( | 4613 ) |
4312 """<b>Profile Data...</b>""" | 4614 self.codeProfileAct.setWhatsThis( |
4313 """<p>This shows the profiling data for the project.</p>""" | 4615 self.tr( |
4314 )) | 4616 """<b>Profile Data...</b>""" |
4617 """<p>This shows the profiling data for the project.</p>""" | |
4618 ) | |
4619 ) | |
4315 self.codeProfileAct.triggered.connect(self.__showProfileData) | 4620 self.codeProfileAct.triggered.connect(self.__showProfileData) |
4316 self.actions.append(self.codeProfileAct) | 4621 self.actions.append(self.codeProfileAct) |
4317 | 4622 |
4318 ################################################################### | 4623 ################################################################### |
4319 ## Project Tools - graphics actions | 4624 ## Project Tools - graphics actions |
4320 ################################################################### | 4625 ################################################################### |
4321 | 4626 |
4322 self.graphicsGrp = createActionGroup(self) | 4627 self.graphicsGrp = createActionGroup(self) |
4323 | 4628 |
4324 self.applicationDiagramAct = EricAction( | 4629 self.applicationDiagramAct = EricAction( |
4325 self.tr('Application Diagram'), | 4630 self.tr("Application Diagram"), |
4326 self.tr('&Application Diagram...'), 0, 0, | 4631 self.tr("&Application Diagram..."), |
4327 self.graphicsGrp, 'project_application_diagram') | 4632 0, |
4633 0, | |
4634 self.graphicsGrp, | |
4635 "project_application_diagram", | |
4636 ) | |
4328 self.applicationDiagramAct.setStatusTip( | 4637 self.applicationDiagramAct.setStatusTip( |
4329 self.tr('Show a diagram of the project.')) | 4638 self.tr("Show a diagram of the project.") |
4330 self.applicationDiagramAct.setWhatsThis(self.tr( | 4639 ) |
4331 """<b>Application Diagram...</b>""" | 4640 self.applicationDiagramAct.setWhatsThis( |
4332 """<p>This shows a diagram of the project.</p>""" | 4641 self.tr( |
4333 )) | 4642 """<b>Application Diagram...</b>""" |
4334 self.applicationDiagramAct.triggered.connect( | 4643 """<p>This shows a diagram of the project.</p>""" |
4335 self.handleApplicationDiagram) | 4644 ) |
4645 ) | |
4646 self.applicationDiagramAct.triggered.connect(self.handleApplicationDiagram) | |
4336 self.actions.append(self.applicationDiagramAct) | 4647 self.actions.append(self.applicationDiagramAct) |
4337 | 4648 |
4338 self.loadDiagramAct = EricAction( | 4649 self.loadDiagramAct = EricAction( |
4339 self.tr('Load Diagram'), | 4650 self.tr("Load Diagram"), |
4340 self.tr('&Load Diagram...'), 0, 0, | 4651 self.tr("&Load Diagram..."), |
4341 self.graphicsGrp, 'project_load_diagram') | 4652 0, |
4342 self.loadDiagramAct.setStatusTip( | 4653 0, |
4343 self.tr('Load a diagram from file.')) | 4654 self.graphicsGrp, |
4344 self.loadDiagramAct.setWhatsThis(self.tr( | 4655 "project_load_diagram", |
4345 """<b>Load Diagram...</b>""" | 4656 ) |
4346 """<p>This loads a diagram from file.</p>""" | 4657 self.loadDiagramAct.setStatusTip(self.tr("Load a diagram from file.")) |
4347 )) | 4658 self.loadDiagramAct.setWhatsThis( |
4659 self.tr( | |
4660 """<b>Load Diagram...</b>""" | |
4661 """<p>This loads a diagram from file.</p>""" | |
4662 ) | |
4663 ) | |
4348 self.loadDiagramAct.triggered.connect(self.__loadDiagram) | 4664 self.loadDiagramAct.triggered.connect(self.__loadDiagram) |
4349 self.actions.append(self.loadDiagramAct) | 4665 self.actions.append(self.loadDiagramAct) |
4350 | 4666 |
4351 ################################################################### | 4667 ################################################################### |
4352 ## Project Tools - plugin packaging actions | 4668 ## Project Tools - plugin packaging actions |
4353 ################################################################### | 4669 ################################################################### |
4354 | 4670 |
4355 self.pluginGrp = createActionGroup(self) | 4671 self.pluginGrp = createActionGroup(self) |
4356 | 4672 |
4357 self.pluginPkgListAct = EricAction( | 4673 self.pluginPkgListAct = EricAction( |
4358 self.tr('Create Package List'), | 4674 self.tr("Create Package List"), |
4359 UI.PixmapCache.getIcon("pluginArchiveList"), | 4675 UI.PixmapCache.getIcon("pluginArchiveList"), |
4360 self.tr('Create &Package List'), 0, 0, | 4676 self.tr("Create &Package List"), |
4361 self.pluginGrp, 'project_plugin_pkglist') | 4677 0, |
4678 0, | |
4679 self.pluginGrp, | |
4680 "project_plugin_pkglist", | |
4681 ) | |
4362 self.pluginPkgListAct.setStatusTip( | 4682 self.pluginPkgListAct.setStatusTip( |
4363 self.tr('Create an initial PKGLIST file for an eric plugin.')) | 4683 self.tr("Create an initial PKGLIST file for an eric plugin.") |
4364 self.pluginPkgListAct.setWhatsThis(self.tr( | 4684 ) |
4365 """<b>Create Package List</b>""" | 4685 self.pluginPkgListAct.setWhatsThis( |
4366 """<p>This creates an initial list of files to include in an""" | 4686 self.tr( |
4367 """ eric plugin archive. The list is created from the project""" | 4687 """<b>Create Package List</b>""" |
4368 """ file.</p>""" | 4688 """<p>This creates an initial list of files to include in an""" |
4369 )) | 4689 """ eric plugin archive. The list is created from the project""" |
4690 """ file.</p>""" | |
4691 ) | |
4692 ) | |
4370 self.pluginPkgListAct.triggered.connect(self.__pluginCreatePkgList) | 4693 self.pluginPkgListAct.triggered.connect(self.__pluginCreatePkgList) |
4371 self.actions.append(self.pluginPkgListAct) | 4694 self.actions.append(self.pluginPkgListAct) |
4372 | 4695 |
4373 self.pluginArchiveAct = EricAction( | 4696 self.pluginArchiveAct = EricAction( |
4374 self.tr('Create Plugin Archives'), | 4697 self.tr("Create Plugin Archives"), |
4375 UI.PixmapCache.getIcon("pluginArchive"), | 4698 UI.PixmapCache.getIcon("pluginArchive"), |
4376 self.tr('Create Plugin &Archives'), 0, 0, | 4699 self.tr("Create Plugin &Archives"), |
4377 self.pluginGrp, 'project_plugin_archive') | 4700 0, |
4378 self.pluginArchiveAct.setStatusTip( | 4701 0, |
4379 self.tr('Create eric plugin archive files.')) | 4702 self.pluginGrp, |
4380 self.pluginArchiveAct.setWhatsThis(self.tr( | 4703 "project_plugin_archive", |
4381 """<b>Create Plugin Archives</b>""" | 4704 ) |
4382 """<p>This creates eric plugin archive files using the list""" | 4705 self.pluginArchiveAct.setStatusTip(self.tr("Create eric plugin archive files.")) |
4383 """ of files given in a PKGLIST* file. The archive name is""" | 4706 self.pluginArchiveAct.setWhatsThis( |
4384 """ built from the main script name if not designated in""" | 4707 self.tr( |
4385 """ the package list file.</p>""" | 4708 """<b>Create Plugin Archives</b>""" |
4386 )) | 4709 """<p>This creates eric plugin archive files using the list""" |
4710 """ of files given in a PKGLIST* file. The archive name is""" | |
4711 """ built from the main script name if not designated in""" | |
4712 """ the package list file.</p>""" | |
4713 ) | |
4714 ) | |
4387 self.pluginArchiveAct.triggered.connect(self.__pluginCreateArchives) | 4715 self.pluginArchiveAct.triggered.connect(self.__pluginCreateArchives) |
4388 self.actions.append(self.pluginArchiveAct) | 4716 self.actions.append(self.pluginArchiveAct) |
4389 | 4717 |
4390 self.pluginSArchiveAct = EricAction( | 4718 self.pluginSArchiveAct = EricAction( |
4391 self.tr('Create Plugin Archives (Snapshot)'), | 4719 self.tr("Create Plugin Archives (Snapshot)"), |
4392 UI.PixmapCache.getIcon("pluginArchiveSnapshot"), | 4720 UI.PixmapCache.getIcon("pluginArchiveSnapshot"), |
4393 self.tr('Create Plugin Archives (&Snapshot)'), 0, 0, | 4721 self.tr("Create Plugin Archives (&Snapshot)"), |
4394 self.pluginGrp, 'project_plugin_sarchive') | 4722 0, |
4395 self.pluginSArchiveAct.setStatusTip(self.tr( | 4723 0, |
4396 'Create eric plugin archive files (snapshot releases).')) | 4724 self.pluginGrp, |
4397 self.pluginSArchiveAct.setWhatsThis(self.tr( | 4725 "project_plugin_sarchive", |
4398 """<b>Create Plugin Archives (Snapshot)</b>""" | 4726 ) |
4399 """<p>This creates eric plugin archive files using the list""" | 4727 self.pluginSArchiveAct.setStatusTip( |
4400 """ of files given in the PKGLIST* file. The archive name is""" | 4728 self.tr("Create eric plugin archive files (snapshot releases).") |
4401 """ built from the main script name if not designated in""" | 4729 ) |
4402 """ the package list file. The version entry of the main script""" | 4730 self.pluginSArchiveAct.setWhatsThis( |
4403 """ is modified to reflect a snapshot release.</p>""" | 4731 self.tr( |
4404 )) | 4732 """<b>Create Plugin Archives (Snapshot)</b>""" |
4405 self.pluginSArchiveAct.triggered.connect( | 4733 """<p>This creates eric plugin archive files using the list""" |
4406 self.__pluginCreateSnapshotArchives) | 4734 """ of files given in the PKGLIST* file. The archive name is""" |
4735 """ built from the main script name if not designated in""" | |
4736 """ the package list file. The version entry of the main script""" | |
4737 """ is modified to reflect a snapshot release.</p>""" | |
4738 ) | |
4739 ) | |
4740 self.pluginSArchiveAct.triggered.connect(self.__pluginCreateSnapshotArchives) | |
4407 self.actions.append(self.pluginSArchiveAct) | 4741 self.actions.append(self.pluginSArchiveAct) |
4408 | 4742 |
4409 ################################################################### | 4743 ################################################################### |
4410 ## Project Tools - make actions | 4744 ## Project Tools - make actions |
4411 ################################################################### | 4745 ################################################################### |
4412 | 4746 |
4413 self.makeGrp = createActionGroup(self) | 4747 self.makeGrp = createActionGroup(self) |
4414 | 4748 |
4415 self.makeExecuteAct = EricAction( | 4749 self.makeExecuteAct = EricAction( |
4416 self.tr('Execute Make'), | 4750 self.tr("Execute Make"), |
4417 self.tr('&Execute Make'), 0, 0, | 4751 self.tr("&Execute Make"), |
4418 self.makeGrp, 'project_make_execute') | 4752 0, |
4419 self.makeExecuteAct.setStatusTip( | 4753 0, |
4420 self.tr("Perform a 'make' run.")) | 4754 self.makeGrp, |
4421 self.makeExecuteAct.setWhatsThis(self.tr( | 4755 "project_make_execute", |
4422 """<b>Execute Make</b>""" | 4756 ) |
4423 """<p>This performs a 'make' run to rebuild the configured""" | 4757 self.makeExecuteAct.setStatusTip(self.tr("Perform a 'make' run.")) |
4424 """ target.</p>""" | 4758 self.makeExecuteAct.setWhatsThis( |
4425 )) | 4759 self.tr( |
4760 """<b>Execute Make</b>""" | |
4761 """<p>This performs a 'make' run to rebuild the configured""" | |
4762 """ target.</p>""" | |
4763 ) | |
4764 ) | |
4426 self.makeExecuteAct.triggered.connect(self.__executeMake) | 4765 self.makeExecuteAct.triggered.connect(self.__executeMake) |
4427 self.actions.append(self.makeExecuteAct) | 4766 self.actions.append(self.makeExecuteAct) |
4428 | 4767 |
4429 self.makeTestAct = EricAction( | 4768 self.makeTestAct = EricAction( |
4430 self.tr('Test for Changes'), | 4769 self.tr("Test for Changes"), |
4431 self.tr('&Test for Changes'), 0, 0, | 4770 self.tr("&Test for Changes"), |
4432 self.makeGrp, 'project_make_test') | 4771 0, |
4772 0, | |
4773 self.makeGrp, | |
4774 "project_make_test", | |
4775 ) | |
4433 self.makeTestAct.setStatusTip( | 4776 self.makeTestAct.setStatusTip( |
4434 self.tr("Question 'make', if a rebuild is needed.")) | 4777 self.tr("Question 'make', if a rebuild is needed.") |
4435 self.makeTestAct.setWhatsThis(self.tr( | 4778 ) |
4436 """<b>Test for Changes</b>""" | 4779 self.makeTestAct.setWhatsThis( |
4437 """<p>This questions 'make', if a rebuild of the configured""" | 4780 self.tr( |
4438 """ target is necessary.</p>""" | 4781 """<b>Test for Changes</b>""" |
4439 )) | 4782 """<p>This questions 'make', if a rebuild of the configured""" |
4783 """ target is necessary.</p>""" | |
4784 ) | |
4785 ) | |
4440 self.makeTestAct.triggered.connect( | 4786 self.makeTestAct.triggered.connect( |
4441 lambda: self.__executeMake(questionOnly=True)) | 4787 lambda: self.__executeMake(questionOnly=True) |
4788 ) | |
4442 self.actions.append(self.makeTestAct) | 4789 self.actions.append(self.makeTestAct) |
4443 | 4790 |
4444 ################################################################### | 4791 ################################################################### |
4445 ## Project Tools - other tools actions | 4792 ## Project Tools - other tools actions |
4446 ################################################################### | 4793 ################################################################### |
4447 | 4794 |
4448 self.othersGrp = createActionGroup(self) | 4795 self.othersGrp = createActionGroup(self) |
4449 | 4796 |
4450 self.createSBOMAct = EricAction( | 4797 self.createSBOMAct = EricAction( |
4451 self.tr('Create SBOM File'), | 4798 self.tr("Create SBOM File"), |
4452 self.tr('Create &SBOM File'), 0, 0, | 4799 self.tr("Create &SBOM File"), |
4453 self.othersGrp, 'project_create_sbom') | 4800 0, |
4801 0, | |
4802 self.othersGrp, | |
4803 "project_create_sbom", | |
4804 ) | |
4454 self.createSBOMAct.setStatusTip( | 4805 self.createSBOMAct.setStatusTip( |
4455 self.tr("Create a SBOM file of the project dependencies.")) | 4806 self.tr("Create a SBOM file of the project dependencies.") |
4456 self.createSBOMAct.setWhatsThis(self.tr( | 4807 ) |
4457 """<b>Create SBOM File</b>""" | 4808 self.createSBOMAct.setWhatsThis( |
4458 """<p>This allows the creation of a SBOM file of the project""" | 4809 self.tr( |
4459 """ dependencies. This may be based on various input sources""" | 4810 """<b>Create SBOM File</b>""" |
4460 """ and will be saved as a CycloneDX SBOM file.</p>""" | 4811 """<p>This allows the creation of a SBOM file of the project""" |
4461 )) | 4812 """ dependencies. This may be based on various input sources""" |
4813 """ and will be saved as a CycloneDX SBOM file.</p>""" | |
4814 ) | |
4815 ) | |
4462 self.createSBOMAct.triggered.connect(self.__createSBOMFile) | 4816 self.createSBOMAct.triggered.connect(self.__createSBOMFile) |
4463 self.actions.append(self.createSBOMAct) | 4817 self.actions.append(self.createSBOMAct) |
4464 | 4818 |
4465 ################################################################### | 4819 ################################################################### |
4466 ## Project Tools - code formatting actions | 4820 ## Project Tools - code formatting actions |
4467 ################################################################### | 4821 ################################################################### |
4468 | 4822 |
4469 self.blackFormattingGrp = createActionGroup(self) | 4823 self.blackFormattingGrp = createActionGroup(self) |
4470 | 4824 |
4471 self.blackAboutAct = EricAction( | 4825 self.blackAboutAct = EricAction( |
4472 self.tr("About Black"), | 4826 self.tr("About Black"), |
4473 self.tr("&Black"), | 4827 self.tr("&Black"), |
4474 0, 0, | 4828 0, |
4475 self.blackFormattingGrp, "project_black_about" | 4829 0, |
4476 ) | 4830 self.blackFormattingGrp, |
4477 self.blackAboutAct.setStatusTip( | 4831 "project_black_about", |
4478 self.tr("Show some information about 'Black'.") | 4832 ) |
4479 ) | 4833 self.blackAboutAct.setStatusTip(self.tr("Show some information about 'Black'.")) |
4480 self.blackAboutAct.setWhatsThis(self.tr( | 4834 self.blackAboutAct.setWhatsThis( |
4481 "<b>Black</b>" | 4835 self.tr( |
4482 "<p>This shows some information about the installed 'Black' tool.</p>" | 4836 "<b>Black</b>" |
4483 )) | 4837 "<p>This shows some information about the installed 'Black' tool.</p>" |
4838 ) | |
4839 ) | |
4484 self.blackAboutAct.triggered.connect(self.__aboutBlack) | 4840 self.blackAboutAct.triggered.connect(self.__aboutBlack) |
4485 self.actions.append(self.blackAboutAct) | 4841 self.actions.append(self.blackAboutAct) |
4486 font = self.blackAboutAct.font() | 4842 font = self.blackAboutAct.font() |
4487 font.setBold(True) | 4843 font.setBold(True) |
4488 self.blackAboutAct.setFont(font) | 4844 self.blackAboutAct.setFont(font) |
4489 | 4845 |
4490 self.blackFormatAct = EricAction( | 4846 self.blackFormatAct = EricAction( |
4491 self.tr("Format Code"), | 4847 self.tr("Format Code"), |
4492 self.tr("&Format Code"), | 4848 self.tr("&Format Code"), |
4493 0, 0, | 4849 0, |
4494 self.blackFormattingGrp, "project_black_format_code" | 4850 0, |
4851 self.blackFormattingGrp, | |
4852 "project_black_format_code", | |
4495 ) | 4853 ) |
4496 self.blackFormatAct.setStatusTip( | 4854 self.blackFormatAct.setStatusTip( |
4497 self.tr("Format the project sources with 'Black'.") | 4855 self.tr("Format the project sources with 'Black'.") |
4498 ) | 4856 ) |
4499 self.blackFormatAct.setWhatsThis(self.tr( | 4857 self.blackFormatAct.setWhatsThis( |
4500 "<b>Format Code</b>" | 4858 self.tr( |
4501 "<p>This shows a dialog to enter parameters for the formatting run and" | 4859 "<b>Format Code</b>" |
4502 " reformats the project sources using 'Black'.</p>" | 4860 "<p>This shows a dialog to enter parameters for the formatting run and" |
4503 )) | 4861 " reformats the project sources using 'Black'.</p>" |
4862 ) | |
4863 ) | |
4504 self.blackFormatAct.triggered.connect( | 4864 self.blackFormatAct.triggered.connect( |
4505 lambda: self.__performFormatWithBlack(BlackFormattingAction.Format) | 4865 lambda: self.__performFormatWithBlack(BlackFormattingAction.Format) |
4506 ) | 4866 ) |
4507 self.actions.append(self.blackFormatAct) | 4867 self.actions.append(self.blackFormatAct) |
4508 | 4868 |
4509 self.blackCheckFormattingAct = EricAction( | 4869 self.blackCheckFormattingAct = EricAction( |
4510 self.tr("Check Code Formatting"), | 4870 self.tr("Check Code Formatting"), |
4511 self.tr("&Check Code Formatting"), | 4871 self.tr("&Check Code Formatting"), |
4512 0, 0, | 4872 0, |
4513 self.blackFormattingGrp, "project_black_check_code" | 4873 0, |
4874 self.blackFormattingGrp, | |
4875 "project_black_check_code", | |
4514 ) | 4876 ) |
4515 self.blackCheckFormattingAct.setStatusTip( | 4877 self.blackCheckFormattingAct.setStatusTip( |
4516 self.tr( | 4878 self.tr( |
4517 "Check, if the project sources need to be reformatted with 'Black'." | 4879 "Check, if the project sources need to be reformatted with 'Black'." |
4518 ) | 4880 ) |
4519 ) | 4881 ) |
4520 self.blackCheckFormattingAct.setWhatsThis(self.tr( | 4882 self.blackCheckFormattingAct.setWhatsThis( |
4521 "<b>Check Code Formatting</b>" | 4883 self.tr( |
4522 "<p>This shows a dialog to enter parameters for the format check run and" | 4884 "<b>Check Code Formatting</b>" |
4523 " performs a check, if the project sources need to be reformatted using" | 4885 "<p>This shows a dialog to enter parameters for the format check run" |
4524 " 'Black'.</p>" | 4886 " and performs a check, if the project sources need to be reformatted" |
4525 )) | 4887 " using Black'.</p>" |
4888 ) | |
4889 ) | |
4526 self.blackCheckFormattingAct.triggered.connect( | 4890 self.blackCheckFormattingAct.triggered.connect( |
4527 lambda: self.__performFormatWithBlack(BlackFormattingAction.Check) | 4891 lambda: self.__performFormatWithBlack(BlackFormattingAction.Check) |
4528 ) | 4892 ) |
4529 self.actions.append(self.blackCheckFormattingAct) | 4893 self.actions.append(self.blackCheckFormattingAct) |
4530 | 4894 |
4531 self.blackDiffFormattingAct = EricAction( | 4895 self.blackDiffFormattingAct = EricAction( |
4532 self.tr("Code Formatting Diff"), | 4896 self.tr("Code Formatting Diff"), |
4533 self.tr("Code Formatting &Diff"), | 4897 self.tr("Code Formatting &Diff"), |
4534 0, 0, | 4898 0, |
4535 self.blackFormattingGrp, "project_black_diff_code" | 4899 0, |
4900 self.blackFormattingGrp, | |
4901 "project_black_diff_code", | |
4536 ) | 4902 ) |
4537 self.blackDiffFormattingAct.setStatusTip( | 4903 self.blackDiffFormattingAct.setStatusTip( |
4538 self.tr( | 4904 self.tr( |
4539 "Generate a unified diff of potential project source reformatting" | 4905 "Generate a unified diff of potential project source reformatting" |
4540 " with 'Black'." | 4906 " with 'Black'." |
4541 ) | 4907 ) |
4542 ) | 4908 ) |
4543 self.blackDiffFormattingAct.setWhatsThis(self.tr( | 4909 self.blackDiffFormattingAct.setWhatsThis( |
4544 "<b>Diff Code Formatting</b>" | 4910 self.tr( |
4545 "<p>This shows a dialog to enter parameters for the format diff run and" | 4911 "<b>Diff Code Formatting</b>" |
4546 " generates a unified diff of potential project source reformatting using" | 4912 "<p>This shows a dialog to enter parameters for the format diff run and" |
4547 " 'Black'.</p>" | 4913 " generates a unified diff of potential project source reformatting" |
4548 )) | 4914 " using Black'.</p>" |
4915 ) | |
4916 ) | |
4549 self.blackDiffFormattingAct.triggered.connect( | 4917 self.blackDiffFormattingAct.triggered.connect( |
4550 lambda: self.__performFormatWithBlack(BlackFormattingAction.Diff) | 4918 lambda: self.__performFormatWithBlack(BlackFormattingAction.Diff) |
4551 ) | 4919 ) |
4552 self.actions.append(self.blackDiffFormattingAct) | 4920 self.actions.append(self.blackDiffFormattingAct) |
4553 | 4921 |
4554 self.closeAct.setEnabled(False) | 4922 self.closeAct.setEnabled(False) |
4555 self.saveAct.setEnabled(False) | 4923 self.saveAct.setEnabled(False) |
4556 self.saveasAct.setEnabled(False) | 4924 self.saveasAct.setEnabled(False) |
4557 self.actGrp2.setEnabled(False) | 4925 self.actGrp2.setEnabled(False) |
4558 self.propsAct.setEnabled(False) | 4926 self.propsAct.setEnabled(False) |
4560 self.filetypesAct.setEnabled(False) | 4928 self.filetypesAct.setEnabled(False) |
4561 self.lexersAct.setEnabled(False) | 4929 self.lexersAct.setEnabled(False) |
4562 self.sessActGrp.setEnabled(False) | 4930 self.sessActGrp.setEnabled(False) |
4563 self.dbgActGrp.setEnabled(False) | 4931 self.dbgActGrp.setEnabled(False) |
4564 self.pluginGrp.setEnabled(False) | 4932 self.pluginGrp.setEnabled(False) |
4565 | 4933 |
4566 def initMenus(self): | 4934 def initMenus(self): |
4567 """ | 4935 """ |
4568 Public slot to initialize the project menus. | 4936 Public slot to initialize the project menus. |
4569 | 4937 |
4570 @return tuple of generated menus | 4938 @return tuple of generated menus |
4571 @rtype tuple of (QMenu, QMenu) | 4939 @rtype tuple of (QMenu, QMenu) |
4572 """ | 4940 """ |
4573 menu = QMenu(self.tr('&Project'), self.parent()) | 4941 menu = QMenu(self.tr("&Project"), self.parent()) |
4574 self.recentMenu = QMenu(self.tr('Open &Recent Projects'), menu) | 4942 self.recentMenu = QMenu(self.tr("Open &Recent Projects"), menu) |
4575 self.sessionMenu = QMenu(self.tr('Session'), menu) | 4943 self.sessionMenu = QMenu(self.tr("Session"), menu) |
4576 self.debuggerMenu = QMenu(self.tr('Debugger'), menu) | 4944 self.debuggerMenu = QMenu(self.tr("Debugger"), menu) |
4577 | 4945 |
4578 toolsMenu = QMenu(self.tr('Project-T&ools'), self.parent()) | 4946 toolsMenu = QMenu(self.tr("Project-T&ools"), self.parent()) |
4579 self.vcsMenu = QMenu(self.tr('&Version Control'), toolsMenu) | 4947 self.vcsMenu = QMenu(self.tr("&Version Control"), toolsMenu) |
4580 self.vcsMenu.setTearOffEnabled(True) | 4948 self.vcsMenu.setTearOffEnabled(True) |
4581 self.vcsProjectHelper.initMenu(self.vcsMenu) | 4949 self.vcsProjectHelper.initMenu(self.vcsMenu) |
4582 self.vcsMenu.setEnabled(self.vcsSoftwareAvailable()) | 4950 self.vcsMenu.setEnabled(self.vcsSoftwareAvailable()) |
4583 self.checksMenu = QMenu(self.tr('Chec&k'), toolsMenu) | 4951 self.checksMenu = QMenu(self.tr("Chec&k"), toolsMenu) |
4584 self.checksMenu.setTearOffEnabled(True) | 4952 self.checksMenu.setTearOffEnabled(True) |
4585 self.formattingMenu = QMenu(self.tr("Code &Formatting"), toolsMenu) | 4953 self.formattingMenu = QMenu(self.tr("Code &Formatting"), toolsMenu) |
4586 self.formattingMenu.setTearOffEnabled(True) | 4954 self.formattingMenu.setTearOffEnabled(True) |
4587 self.menuShow = QMenu(self.tr('Sho&w'), toolsMenu) | 4955 self.menuShow = QMenu(self.tr("Sho&w"), toolsMenu) |
4588 self.graphicsMenu = QMenu(self.tr('&Diagrams'), toolsMenu) | 4956 self.graphicsMenu = QMenu(self.tr("&Diagrams"), toolsMenu) |
4589 self.packagersMenu = QMenu(self.tr('Pac&kagers'), toolsMenu) | 4957 self.packagersMenu = QMenu(self.tr("Pac&kagers"), toolsMenu) |
4590 self.apidocMenu = QMenu(self.tr('Source &Documentation'), toolsMenu) | 4958 self.apidocMenu = QMenu(self.tr("Source &Documentation"), toolsMenu) |
4591 self.apidocMenu.setTearOffEnabled(True) | 4959 self.apidocMenu.setTearOffEnabled(True) |
4592 self.makeMenu = QMenu(self.tr('Make'), toolsMenu) | 4960 self.makeMenu = QMenu(self.tr("Make"), toolsMenu) |
4593 self.othersMenu = QMenu(self.tr('Other Tools'), toolsMenu) | 4961 self.othersMenu = QMenu(self.tr("Other Tools"), toolsMenu) |
4594 | 4962 |
4595 self.__menus = { | 4963 self.__menus = { |
4596 "Main": menu, | 4964 "Main": menu, |
4597 "Recent": self.recentMenu, | 4965 "Recent": self.recentMenu, |
4598 "VCS": self.vcsMenu, | 4966 "VCS": self.vcsMenu, |
4599 "Checks": self.checksMenu, | 4967 "Checks": self.checksMenu, |
4605 "Packagers": self.packagersMenu, | 4973 "Packagers": self.packagersMenu, |
4606 "Make": self.makeMenu, | 4974 "Make": self.makeMenu, |
4607 "OtherTools": self.othersMenu, | 4975 "OtherTools": self.othersMenu, |
4608 "Formatting": self.formattingMenu, | 4976 "Formatting": self.formattingMenu, |
4609 } | 4977 } |
4610 | 4978 |
4611 # connect the aboutToShow signals | 4979 # connect the aboutToShow signals |
4612 self.recentMenu.aboutToShow.connect(self.__showContextMenuRecent) | 4980 self.recentMenu.aboutToShow.connect(self.__showContextMenuRecent) |
4613 self.recentMenu.triggered.connect(self.__openRecent) | 4981 self.recentMenu.triggered.connect(self.__openRecent) |
4614 self.vcsMenu.aboutToShow.connect(self.__showContextMenuVCS) | 4982 self.vcsMenu.aboutToShow.connect(self.__showContextMenuVCS) |
4615 self.checksMenu.aboutToShow.connect(self.__showContextMenuChecks) | 4983 self.checksMenu.aboutToShow.connect(self.__showContextMenuChecks) |
4621 self.debuggerMenu.aboutToShow.connect(self.__showContextMenuDebugger) | 4989 self.debuggerMenu.aboutToShow.connect(self.__showContextMenuDebugger) |
4622 self.makeMenu.aboutToShow.connect(self.__showContextMenuMake) | 4990 self.makeMenu.aboutToShow.connect(self.__showContextMenuMake) |
4623 self.othersMenu.aboutToShow.connect(self.__showContextMenuOthers) | 4991 self.othersMenu.aboutToShow.connect(self.__showContextMenuOthers) |
4624 self.formattingMenu.aboutToShow.connect(self.__showContextMenuFormat) | 4992 self.formattingMenu.aboutToShow.connect(self.__showContextMenuFormat) |
4625 menu.aboutToShow.connect(self.__showMenu) | 4993 menu.aboutToShow.connect(self.__showMenu) |
4626 | 4994 |
4627 # build the show menu | 4995 # build the show menu |
4628 self.menuShow.setTearOffEnabled(True) | 4996 self.menuShow.setTearOffEnabled(True) |
4629 self.menuShow.addAction(self.codeMetricsAct) | 4997 self.menuShow.addAction(self.codeMetricsAct) |
4630 self.menuShow.addAction(self.codeCoverageAct) | 4998 self.menuShow.addAction(self.codeCoverageAct) |
4631 self.menuShow.addAction(self.codeProfileAct) | 4999 self.menuShow.addAction(self.codeProfileAct) |
4632 | 5000 |
4633 # build the diagrams menu | 5001 # build the diagrams menu |
4634 self.graphicsMenu.setTearOffEnabled(True) | 5002 self.graphicsMenu.setTearOffEnabled(True) |
4635 self.graphicsMenu.addAction(self.applicationDiagramAct) | 5003 self.graphicsMenu.addAction(self.applicationDiagramAct) |
4636 self.graphicsMenu.addSeparator() | 5004 self.graphicsMenu.addSeparator() |
4637 self.graphicsMenu.addAction(self.loadDiagramAct) | 5005 self.graphicsMenu.addAction(self.loadDiagramAct) |
4638 | 5006 |
4639 # build the session menu | 5007 # build the session menu |
4640 self.sessionMenu.setTearOffEnabled(True) | 5008 self.sessionMenu.setTearOffEnabled(True) |
4641 self.sessionMenu.addActions(self.sessActGrp.actions()) | 5009 self.sessionMenu.addActions(self.sessActGrp.actions()) |
4642 | 5010 |
4643 # build the debugger menu | 5011 # build the debugger menu |
4644 self.debuggerMenu.setTearOffEnabled(True) | 5012 self.debuggerMenu.setTearOffEnabled(True) |
4645 self.debuggerMenu.addActions(self.dbgActGrp.actions()) | 5013 self.debuggerMenu.addActions(self.dbgActGrp.actions()) |
4646 | 5014 |
4647 # build the packagers menu | 5015 # build the packagers menu |
4648 self.packagersMenu.setTearOffEnabled(True) | 5016 self.packagersMenu.setTearOffEnabled(True) |
4649 self.packagersMenu.addActions(self.pluginGrp.actions()) | 5017 self.packagersMenu.addActions(self.pluginGrp.actions()) |
4650 self.packagersMenu.addSeparator() | 5018 self.packagersMenu.addSeparator() |
4651 | 5019 |
4652 # build the make menu | 5020 # build the make menu |
4653 self.makeMenu.setTearOffEnabled(True) | 5021 self.makeMenu.setTearOffEnabled(True) |
4654 self.makeMenu.addActions(self.makeGrp.actions()) | 5022 self.makeMenu.addActions(self.makeGrp.actions()) |
4655 self.makeMenu.addSeparator() | 5023 self.makeMenu.addSeparator() |
4656 | 5024 |
4657 # build the 'Other Tools' menu | 5025 # build the 'Other Tools' menu |
4658 self.othersMenu.setTearOffEnabled(True) | 5026 self.othersMenu.setTearOffEnabled(True) |
4659 self.othersMenu.addActions(self.othersGrp.actions()) | 5027 self.othersMenu.addActions(self.othersGrp.actions()) |
4660 self.othersMenu.addSeparator() | 5028 self.othersMenu.addSeparator() |
4661 | 5029 |
4662 # build the 'Code Formatting' menu | 5030 # build the 'Code Formatting' menu |
4663 self.formattingMenu.setTearOffEnabled(True) | 5031 self.formattingMenu.setTearOffEnabled(True) |
4664 self.formattingMenu.addActions(self.blackFormattingGrp.actions()) | 5032 self.formattingMenu.addActions(self.blackFormattingGrp.actions()) |
4665 self.formattingMenu.addSeparator() | 5033 self.formattingMenu.addSeparator() |
4666 | 5034 |
4667 # build the project main menu | 5035 # build the project main menu |
4668 menu.setTearOffEnabled(True) | 5036 menu.setTearOffEnabled(True) |
4669 menu.addActions(self.actGrp1.actions()) | 5037 menu.addActions(self.actGrp1.actions()) |
4670 self.menuRecentAct = menu.addMenu(self.recentMenu) | 5038 self.menuRecentAct = menu.addMenu(self.recentMenu) |
4671 menu.addSeparator() | 5039 menu.addSeparator() |
4681 menu.addAction(self.filetypesAct) | 5049 menu.addAction(self.filetypesAct) |
4682 menu.addAction(self.lexersAct) | 5050 menu.addAction(self.lexersAct) |
4683 menu.addSeparator() | 5051 menu.addSeparator() |
4684 self.menuDebuggerAct = menu.addMenu(self.debuggerMenu) | 5052 self.menuDebuggerAct = menu.addMenu(self.debuggerMenu) |
4685 self.menuSessionAct = menu.addMenu(self.sessionMenu) | 5053 self.menuSessionAct = menu.addMenu(self.sessionMenu) |
4686 | 5054 |
4687 # build the project tools menu | 5055 # build the project tools menu |
4688 toolsMenu.setTearOffEnabled(True) | 5056 toolsMenu.setTearOffEnabled(True) |
4689 toolsMenu.addSeparator() | 5057 toolsMenu.addSeparator() |
4690 toolsMenu.addMenu(self.vcsMenu) | 5058 toolsMenu.addMenu(self.vcsMenu) |
4691 toolsMenu.addSeparator() | 5059 toolsMenu.addSeparator() |
4702 self.menuApidocAct = toolsMenu.addMenu(self.apidocMenu) | 5070 self.menuApidocAct = toolsMenu.addMenu(self.apidocMenu) |
4703 toolsMenu.addSeparator() | 5071 toolsMenu.addSeparator() |
4704 self.menuPackagersAct = toolsMenu.addMenu(self.packagersMenu) | 5072 self.menuPackagersAct = toolsMenu.addMenu(self.packagersMenu) |
4705 toolsMenu.addSeparator() | 5073 toolsMenu.addSeparator() |
4706 self.menuOtherToolsAct = toolsMenu.addMenu(self.othersMenu) | 5074 self.menuOtherToolsAct = toolsMenu.addMenu(self.othersMenu) |
4707 | 5075 |
4708 self.menuCheckAct.setEnabled(False) | 5076 self.menuCheckAct.setEnabled(False) |
4709 self.menuShowAct.setEnabled(False) | 5077 self.menuShowAct.setEnabled(False) |
4710 self.menuDiagramAct.setEnabled(False) | 5078 self.menuDiagramAct.setEnabled(False) |
4711 self.menuSessionAct.setEnabled(False) | 5079 self.menuSessionAct.setEnabled(False) |
4712 self.menuDebuggerAct.setEnabled(False) | 5080 self.menuDebuggerAct.setEnabled(False) |
4713 self.menuApidocAct.setEnabled(False) | 5081 self.menuApidocAct.setEnabled(False) |
4714 self.menuPackagersAct.setEnabled(False) | 5082 self.menuPackagersAct.setEnabled(False) |
4715 self.menuMakeAct.setEnabled(False) | 5083 self.menuMakeAct.setEnabled(False) |
4716 self.menuOtherToolsAct.setEnabled(False) | 5084 self.menuOtherToolsAct.setEnabled(False) |
4717 self.menuFormattingAct.setEnabled(False) | 5085 self.menuFormattingAct.setEnabled(False) |
4718 | 5086 |
4719 self.__menu = menu | 5087 self.__menu = menu |
4720 self.__toolsMenu = toolsMenu | 5088 self.__toolsMenu = toolsMenu |
4721 | 5089 |
4722 return menu, toolsMenu | 5090 return menu, toolsMenu |
4723 | 5091 |
4724 def initToolbars(self, toolbarManager): | 5092 def initToolbars(self, toolbarManager): |
4725 """ | 5093 """ |
4726 Public slot to initialize the project toolbar and the basic VCS | 5094 Public slot to initialize the project toolbar and the basic VCS |
4727 toolbar. | 5095 toolbar. |
4728 | 5096 |
4729 @param toolbarManager reference to a toolbar manager object | 5097 @param toolbarManager reference to a toolbar manager object |
4730 (EricToolBarManager) | 5098 (EricToolBarManager) |
4731 @return tuple of the generated toolbars (tuple of two QToolBar) | 5099 @return tuple of the generated toolbars (tuple of two QToolBar) |
4732 """ | 5100 """ |
4733 tb = QToolBar(self.tr("Project"), self.ui) | 5101 tb = QToolBar(self.tr("Project"), self.ui) |
4734 tb.setIconSize(UI.Config.ToolBarIconSize) | 5102 tb.setIconSize(UI.Config.ToolBarIconSize) |
4735 tb.setObjectName("ProjectToolbar") | 5103 tb.setObjectName("ProjectToolbar") |
4736 tb.setToolTip(self.tr('Project')) | 5104 tb.setToolTip(self.tr("Project")) |
4737 | 5105 |
4738 tb.addActions(self.actGrp1.actions()) | 5106 tb.addActions(self.actGrp1.actions()) |
4739 tb.addAction(self.closeAct) | 5107 tb.addAction(self.closeAct) |
4740 tb.addSeparator() | 5108 tb.addSeparator() |
4741 tb.addAction(self.saveAct) | 5109 tb.addAction(self.saveAct) |
4742 tb.addAction(self.saveasAct) | 5110 tb.addAction(self.saveasAct) |
4743 | 5111 |
4744 toolbarManager.addToolBar(tb, tb.windowTitle()) | 5112 toolbarManager.addToolBar(tb, tb.windowTitle()) |
4745 toolbarManager.addAction(self.addFilesAct, tb.windowTitle()) | 5113 toolbarManager.addAction(self.addFilesAct, tb.windowTitle()) |
4746 toolbarManager.addAction(self.addDirectoryAct, tb.windowTitle()) | 5114 toolbarManager.addAction(self.addDirectoryAct, tb.windowTitle()) |
4747 toolbarManager.addAction(self.addLanguageAct, tb.windowTitle()) | 5115 toolbarManager.addAction(self.addLanguageAct, tb.windowTitle()) |
4748 toolbarManager.addAction(self.propsAct, tb.windowTitle()) | 5116 toolbarManager.addAction(self.propsAct, tb.windowTitle()) |
4749 toolbarManager.addAction(self.userPropsAct, tb.windowTitle()) | 5117 toolbarManager.addAction(self.userPropsAct, tb.windowTitle()) |
4750 | 5118 |
4751 import VCS | 5119 import VCS |
4752 vcstb = VCS.getBasicHelper(self).initBasicToolbar( | 5120 |
4753 self.ui, toolbarManager) | 5121 vcstb = VCS.getBasicHelper(self).initBasicToolbar(self.ui, toolbarManager) |
4754 | 5122 |
4755 return tb, vcstb | 5123 return tb, vcstb |
4756 | 5124 |
4757 def __showMenu(self): | 5125 def __showMenu(self): |
4758 """ | 5126 """ |
4759 Private method to set up the project menu. | 5127 Private method to set up the project menu. |
4760 """ | 5128 """ |
4761 self.menuRecentAct.setEnabled(len(self.recent) > 0) | 5129 self.menuRecentAct.setEnabled(len(self.recent) > 0) |
4762 | 5130 |
4763 self.showMenu.emit("Main", self.__menus["Main"]) | 5131 self.showMenu.emit("Main", self.__menus["Main"]) |
4764 | 5132 |
4765 def __syncRecent(self): | 5133 def __syncRecent(self): |
4766 """ | 5134 """ |
4767 Private method to synchronize the list of recently opened projects | 5135 Private method to synchronize the list of recently opened projects |
4768 with the central store. | 5136 with the central store. |
4769 """ | 5137 """ |
4773 self.recent.insert(0, self.pfile) | 5141 self.recent.insert(0, self.pfile) |
4774 maxRecent = Preferences.getProject("RecentNumber") | 5142 maxRecent = Preferences.getProject("RecentNumber") |
4775 if len(self.recent) > maxRecent: | 5143 if len(self.recent) > maxRecent: |
4776 self.recent = self.recent[:maxRecent] | 5144 self.recent = self.recent[:maxRecent] |
4777 self.__saveRecent() | 5145 self.__saveRecent() |
4778 | 5146 |
4779 def __showContextMenuRecent(self): | 5147 def __showContextMenuRecent(self): |
4780 """ | 5148 """ |
4781 Private method to set up the recent projects menu. | 5149 Private method to set up the recent projects menu. |
4782 """ | 5150 """ |
4783 self.__loadRecent() | 5151 self.__loadRecent() |
4784 | 5152 |
4785 self.recentMenu.clear() | 5153 self.recentMenu.clear() |
4786 | 5154 |
4787 for idx, rp in enumerate(self.recent, start=1): | 5155 for idx, rp in enumerate(self.recent, start=1): |
4788 formatStr = '&{0:d}. {1}' if idx < 10 else '{0:d}. {1}' | 5156 formatStr = "&{0:d}. {1}" if idx < 10 else "{0:d}. {1}" |
4789 act = self.recentMenu.addAction( | 5157 act = self.recentMenu.addAction( |
4790 formatStr.format( | 5158 formatStr.format( |
4791 idx, | 5159 idx, Utilities.compactPath(rp, self.ui.maxMenuFilePathLen) |
4792 Utilities.compactPath(rp, self.ui.maxMenuFilePathLen))) | 5160 ) |
5161 ) | |
4793 act.setData(rp) | 5162 act.setData(rp) |
4794 act.setEnabled(pathlib.Path(rp).exists()) | 5163 act.setEnabled(pathlib.Path(rp).exists()) |
4795 | 5164 |
4796 self.recentMenu.addSeparator() | 5165 self.recentMenu.addSeparator() |
4797 self.recentMenu.addAction(self.tr('&Clear'), self.clearRecent) | 5166 self.recentMenu.addAction(self.tr("&Clear"), self.clearRecent) |
4798 | 5167 |
4799 def __openRecent(self, act): | 5168 def __openRecent(self, act): |
4800 """ | 5169 """ |
4801 Private method to open a project from the list of rencently opened | 5170 Private method to open a project from the list of rencently opened |
4802 projects. | 5171 projects. |
4803 | 5172 |
4804 @param act reference to the action that triggered (QAction) | 5173 @param act reference to the action that triggered (QAction) |
4805 """ | 5174 """ |
4806 file = act.data() | 5175 file = act.data() |
4807 if file: | 5176 if file: |
4808 self.openProject(file) | 5177 self.openProject(file) |
4809 | 5178 |
4810 def clearRecent(self): | 5179 def clearRecent(self): |
4811 """ | 5180 """ |
4812 Public method to clear the recent projects menu. | 5181 Public method to clear the recent projects menu. |
4813 """ | 5182 """ |
4814 self.recent = [] | 5183 self.recent = [] |
4815 self.__saveRecent() | 5184 self.__saveRecent() |
4816 | 5185 |
4817 def clearHistories(self): | 5186 def clearHistories(self): |
4818 """ | 5187 """ |
4819 Public method to clear the project related histories. | 5188 Public method to clear the project related histories. |
4820 """ | 5189 """ |
4821 self.clearRecent() | 5190 self.clearRecent() |
4822 | 5191 |
4823 for key in ["DebugClientsHistory", "DebuggerInterpreterHistory"]: | 5192 for key in ["DebugClientsHistory", "DebuggerInterpreterHistory"]: |
4824 Preferences.setProject(key, []) | 5193 Preferences.setProject(key, []) |
4825 Preferences.syncPreferences() | 5194 Preferences.syncPreferences() |
4826 | 5195 |
4827 def __searchNewFiles(self): | 5196 def __searchNewFiles(self): |
4828 """ | 5197 """ |
4829 Private slot used to handle the search new files action. | 5198 Private slot used to handle the search new files action. |
4830 """ | 5199 """ |
4831 self.__doSearchNewFiles(False, True) | 5200 self.__doSearchNewFiles(False, True) |
4832 | 5201 |
4833 def __searchProjectFile(self): | 5202 def __searchProjectFile(self): |
4834 """ | 5203 """ |
4835 Private slot to show the Find Project File dialog. | 5204 Private slot to show the Find Project File dialog. |
4836 """ | 5205 """ |
4837 if self.__findProjectFileDialog is None: | 5206 if self.__findProjectFileDialog is None: |
4838 from .QuickFindFileDialog import QuickFindFileDialog | 5207 from .QuickFindFileDialog import QuickFindFileDialog |
5208 | |
4839 self.__findProjectFileDialog = QuickFindFileDialog(self) | 5209 self.__findProjectFileDialog = QuickFindFileDialog(self) |
4840 self.__findProjectFileDialog.sourceFile.connect( | 5210 self.__findProjectFileDialog.sourceFile.connect(self.sourceFile) |
4841 self.sourceFile) | 5211 self.__findProjectFileDialog.designerFile.connect(self.designerFile) |
4842 self.__findProjectFileDialog.designerFile.connect( | 5212 self.__findProjectFileDialog.linguistFile.connect(self.linguistFile) |
4843 self.designerFile) | |
4844 self.__findProjectFileDialog.linguistFile.connect( | |
4845 self.linguistFile) | |
4846 self.__findProjectFileDialog.show() | 5213 self.__findProjectFileDialog.show() |
4847 self.__findProjectFileDialog.raise_() | 5214 self.__findProjectFileDialog.raise_() |
4848 self.__findProjectFileDialog.activateWindow() | 5215 self.__findProjectFileDialog.activateWindow() |
4849 | 5216 |
4850 def __doSearchNewFiles(self, AI=True, onUserDemand=False): | 5217 def __doSearchNewFiles(self, AI=True, onUserDemand=False): |
4851 """ | 5218 """ |
4852 Private method to search for new files in the project directory. | 5219 Private method to search for new files in the project directory. |
4853 | 5220 |
4854 If new files were found, it shows a dialog listing these files and | 5221 If new files were found, it shows a dialog listing these files and |
4855 gives the user the opportunity to select the ones he wants to | 5222 gives the user the opportunity to select the ones he wants to |
4856 include. If 'Automatic Inclusion' is enabled, the new files are | 5223 include. If 'Automatic Inclusion' is enabled, the new files are |
4857 automatically added to the project. | 5224 automatically added to the project. |
4858 | 5225 |
4859 @param AI flag indicating whether the automatic inclusion should | 5226 @param AI flag indicating whether the automatic inclusion should |
4860 be honoured (boolean) | 5227 be honoured (boolean) |
4861 @param onUserDemand flag indicating whether this method was | 5228 @param onUserDemand flag indicating whether this method was |
4862 requested by the user via a menu action (boolean) | 5229 requested by the user via a menu action (boolean) |
4863 """ | 5230 """ |
4864 autoInclude = Preferences.getProject("AutoIncludeNewFiles") | 5231 autoInclude = Preferences.getProject("AutoIncludeNewFiles") |
4865 recursiveSearch = Preferences.getProject("SearchNewFilesRecursively") | 5232 recursiveSearch = Preferences.getProject("SearchNewFilesRecursively") |
4866 newFiles = [] | 5233 newFiles = [] |
4867 | 5234 |
4868 ignore_patterns = [pattern for pattern, filetype in | 5235 ignore_patterns = [ |
4869 self.pdata["FILETYPES"].items() | 5236 pattern |
4870 if filetype == '__IGNORE__'] | 5237 for pattern, filetype in self.pdata["FILETYPES"].items() |
4871 | 5238 if filetype == "__IGNORE__" |
5239 ] | |
5240 | |
4872 dirs = self.subdirs[:] | 5241 dirs = self.subdirs[:] |
4873 for directory in dirs: | 5242 for directory in dirs: |
4874 skip = False | 5243 skip = False |
4875 for ignore_pattern in ignore_patterns: | 5244 for ignore_pattern in ignore_patterns: |
4876 if fnmatch.fnmatch(directory, ignore_pattern): | 5245 if fnmatch.fnmatch(directory, ignore_pattern): |
4877 skip = True | 5246 skip = True |
4878 break | 5247 break |
4879 if skip: | 5248 if skip: |
4880 continue | 5249 continue |
4881 | 5250 |
4882 curpath = os.path.join(self.ppath, directory) | 5251 curpath = os.path.join(self.ppath, directory) |
4883 try: | 5252 try: |
4884 newSources = os.listdir(curpath) | 5253 newSources = os.listdir(curpath) |
4885 except OSError: | 5254 except OSError: |
4886 newSources = [] | 5255 newSources = [] |
4887 pattern = ( | 5256 pattern = ( |
4888 self.pdata["TRANSLATIONPATTERN"].replace("%language%", "*") | 5257 self.pdata["TRANSLATIONPATTERN"].replace("%language%", "*") |
4889 if self.pdata["TRANSLATIONPATTERN"] else | 5258 if self.pdata["TRANSLATIONPATTERN"] |
4890 "*.ts" | 5259 else "*.ts" |
4891 ) | 5260 ) |
4892 binpattern = self.__binaryTranslationFile(pattern) | 5261 binpattern = self.__binaryTranslationFile(pattern) |
4893 for ns in newSources: | 5262 for ns in newSources: |
4894 # ignore hidden files and directories | 5263 # ignore hidden files and directories |
4895 if ns.startswith('.'): | 5264 if ns.startswith("."): |
4896 continue | 5265 continue |
4897 if ( | 5266 if ( |
4898 Utilities.isWindowsPlatform() and | 5267 Utilities.isWindowsPlatform() |
4899 os.path.isdir(os.path.join(curpath, ns)) and | 5268 and os.path.isdir(os.path.join(curpath, ns)) |
4900 ns.startswith('_') | 5269 and ns.startswith("_") |
4901 ): | 5270 ): |
4902 # dot net hack | 5271 # dot net hack |
4903 continue | 5272 continue |
4904 | 5273 |
4905 # set fn to project relative name | 5274 # set fn to project relative name |
4906 # then reset ns to fully qualified name for insertion, | 5275 # then reset ns to fully qualified name for insertion, |
4907 # possibly. | 5276 # possibly. |
4908 fn = os.path.join(directory, ns) if directory else ns | 5277 fn = os.path.join(directory, ns) if directory else ns |
4909 ns = os.path.abspath(os.path.join(curpath, ns)) | 5278 ns = os.path.abspath(os.path.join(curpath, ns)) |
4910 | 5279 |
4911 # do not bother with dirs here... | 5280 # do not bother with dirs here... |
4912 if os.path.isdir(ns): | 5281 if os.path.isdir(ns): |
4913 if recursiveSearch: | 5282 if recursiveSearch: |
4914 d = self.getRelativePath(ns) | 5283 d = self.getRelativePath(ns) |
4915 if d not in dirs: | 5284 if d not in dirs: |
4916 dirs.append(d) | 5285 dirs.append(d) |
4917 continue | 5286 continue |
4918 | 5287 |
4919 filetype = "" | 5288 filetype = "" |
4920 bfn = os.path.basename(fn) | 5289 bfn = os.path.basename(fn) |
4921 for pattern in sorted(self.pdata["FILETYPES"].keys(), | 5290 for pattern in sorted(self.pdata["FILETYPES"].keys(), reverse=True): |
4922 reverse=True): | |
4923 if fnmatch.fnmatch(bfn, pattern): | 5291 if fnmatch.fnmatch(bfn, pattern): |
4924 filetype = self.pdata["FILETYPES"][pattern] | 5292 filetype = self.pdata["FILETYPES"][pattern] |
4925 break | 5293 break |
4926 | 5294 |
4927 if ( | 5295 if ( |
4928 (filetype == "SOURCES" and | 5296 (filetype == "SOURCES" and fn not in self.pdata["SOURCES"]) |
4929 fn not in self.pdata["SOURCES"]) or | 5297 or (filetype == "FORMS" and fn not in self.pdata["FORMS"]) |
4930 (filetype == "FORMS" and | 5298 or (filetype == "INTERFACES" and fn not in self.pdata["INTERFACES"]) |
4931 fn not in self.pdata["FORMS"]) or | 5299 or (filetype == "PROTOCOLS" and fn not in self.pdata["PROTOCOLS"]) |
4932 (filetype == "INTERFACES" and | 5300 or (filetype == "RESOURCES" and fn not in self.pdata["RESOURCES"]) |
4933 fn not in self.pdata["INTERFACES"]) or | 5301 or (filetype == "OTHERS" and fn not in self.pdata["OTHERS"]) |
4934 (filetype == "PROTOCOLS" and | 5302 or ( |
4935 fn not in self.pdata["PROTOCOLS"]) or | 5303 filetype == "TRANSLATIONS" |
4936 (filetype == "RESOURCES" and | 5304 and fn not in self.pdata["TRANSLATIONS"] |
4937 fn not in self.pdata["RESOURCES"]) or | 5305 and ( |
4938 (filetype == "OTHERS" and | 5306 fnmatch.fnmatch(ns, pattern) |
4939 fn not in self.pdata["OTHERS"]) or | 5307 or fnmatch.fnmatch(ns, binpattern) |
4940 (filetype == "TRANSLATIONS" and | 5308 ) |
4941 fn not in self.pdata["TRANSLATIONS"] and | 5309 ) |
4942 (fnmatch.fnmatch(ns, pattern) or | |
4943 fnmatch.fnmatch(ns, binpattern))) | |
4944 ): | 5310 ): |
4945 if autoInclude and AI: | 5311 if autoInclude and AI: |
4946 self.appendFile(ns) | 5312 self.appendFile(ns) |
4947 else: | 5313 else: |
4948 newFiles.append(ns) | 5314 newFiles.append(ns) |
4949 | 5315 |
4950 # if autoInclude is set there is no more work left | 5316 # if autoInclude is set there is no more work left |
4951 if (autoInclude and AI): | 5317 if autoInclude and AI: |
4952 return | 5318 return |
4953 | 5319 |
4954 # if newfiles is empty, put up message box informing user nothing found | 5320 # if newfiles is empty, put up message box informing user nothing found |
4955 if not newFiles: | 5321 if not newFiles: |
4956 if onUserDemand: | 5322 if onUserDemand: |
4957 EricMessageBox.information( | 5323 EricMessageBox.information( |
4958 self.ui, | 5324 self.ui, |
4959 self.tr("Search New Files"), | 5325 self.tr("Search New Files"), |
4960 self.tr("There were no new files found to be added.")) | 5326 self.tr("There were no new files found to be added."), |
5327 ) | |
4961 return | 5328 return |
4962 | 5329 |
4963 # autoInclude is not set, show a dialog | 5330 # autoInclude is not set, show a dialog |
4964 from .AddFoundFilesDialog import AddFoundFilesDialog | 5331 from .AddFoundFilesDialog import AddFoundFilesDialog |
5332 | |
4965 dlg = AddFoundFilesDialog(newFiles, self.parent(), None) | 5333 dlg = AddFoundFilesDialog(newFiles, self.parent(), None) |
4966 res = dlg.exec() | 5334 res = dlg.exec() |
4967 | 5335 |
4968 # the 'Add All' button was pressed | 5336 # the 'Add All' button was pressed |
4969 if res == 1: | 5337 if res == 1: |
4970 for file in newFiles: | 5338 for file in newFiles: |
4971 self.appendFile(file) | 5339 self.appendFile(file) |
4972 | 5340 |
4973 # the 'Add Selected' button was pressed | 5341 # the 'Add Selected' button was pressed |
4974 elif res == 2: | 5342 elif res == 2: |
4975 files = dlg.getSelection() | 5343 files = dlg.getSelection() |
4976 for file in files: | 5344 for file in files: |
4977 self.appendFile(file) | 5345 self.appendFile(file) |
4978 | 5346 |
4979 def othersAdded(self, fn, updateModel=True): | 5347 def othersAdded(self, fn, updateModel=True): |
4980 """ | 5348 """ |
4981 Public slot to be called, if something was added to the OTHERS project | 5349 Public slot to be called, if something was added to the OTHERS project |
4982 data area. | 5350 data area. |
4983 | 5351 |
4984 @param fn filename or directory name added (string) | 5352 @param fn filename or directory name added (string) |
4985 @param updateModel flag indicating an update of the model is requested | 5353 @param updateModel flag indicating an update of the model is requested |
4986 (boolean) | 5354 (boolean) |
4987 """ | 5355 """ |
4988 self.projectOthersAdded.emit(fn) | 5356 self.projectOthersAdded.emit(fn) |
4989 updateModel and self.__model.addNewItem("OTHERS", fn) | 5357 updateModel and self.__model.addNewItem("OTHERS", fn) |
4990 | 5358 |
4991 def getActions(self): | 5359 def getActions(self): |
4992 """ | 5360 """ |
4993 Public method to get a list of all actions. | 5361 Public method to get a list of all actions. |
4994 | 5362 |
4995 @return list of all actions (list of EricAction) | 5363 @return list of all actions (list of EricAction) |
4996 """ | 5364 """ |
4997 return self.actions[:] | 5365 return self.actions[:] |
4998 | 5366 |
4999 def addEricActions(self, actions): | 5367 def addEricActions(self, actions): |
5000 """ | 5368 """ |
5001 Public method to add actions to the list of actions. | 5369 Public method to add actions to the list of actions. |
5002 | 5370 |
5003 @param actions list of actions (list of EricAction) | 5371 @param actions list of actions (list of EricAction) |
5004 """ | 5372 """ |
5005 self.actions.extend(actions) | 5373 self.actions.extend(actions) |
5006 | 5374 |
5007 def removeEricActions(self, actions): | 5375 def removeEricActions(self, actions): |
5008 """ | 5376 """ |
5009 Public method to remove actions from the list of actions. | 5377 Public method to remove actions from the list of actions. |
5010 | 5378 |
5011 @param actions list of actions (list of EricAction) | 5379 @param actions list of actions (list of EricAction) |
5012 """ | 5380 """ |
5013 for act in actions: | 5381 for act in actions: |
5014 with contextlib.suppress(ValueError): | 5382 with contextlib.suppress(ValueError): |
5015 self.actions.remove(act) | 5383 self.actions.remove(act) |
5016 | 5384 |
5017 def getMenu(self, menuName): | 5385 def getMenu(self, menuName): |
5018 """ | 5386 """ |
5019 Public method to get a reference to the main menu or a submenu. | 5387 Public method to get a reference to the main menu or a submenu. |
5020 | 5388 |
5021 @param menuName name of the menu (string) | 5389 @param menuName name of the menu (string) |
5022 @return reference to the requested menu (QMenu) or None | 5390 @return reference to the requested menu (QMenu) or None |
5023 """ | 5391 """ |
5024 try: | 5392 try: |
5025 return self.__menus[menuName] | 5393 return self.__menus[menuName] |
5026 except KeyError: | 5394 except KeyError: |
5027 return None | 5395 return None |
5028 | 5396 |
5029 def repopulateItem(self, fullname): | 5397 def repopulateItem(self, fullname): |
5030 """ | 5398 """ |
5031 Public slot to repopulate a named item. | 5399 Public slot to repopulate a named item. |
5032 | 5400 |
5033 @param fullname full name of the item to repopulate (string) | 5401 @param fullname full name of the item to repopulate (string) |
5034 """ | 5402 """ |
5035 if not self.isOpen(): | 5403 if not self.isOpen(): |
5036 return | 5404 return |
5037 | 5405 |
5038 with EricOverrideCursor(): | 5406 with EricOverrideCursor(): |
5039 name = self.getRelativePath(fullname) | 5407 name = self.getRelativePath(fullname) |
5040 self.prepareRepopulateItem.emit(name) | 5408 self.prepareRepopulateItem.emit(name) |
5041 self.__model.repopulateItem(name) | 5409 self.__model.repopulateItem(name) |
5042 self.completeRepopulateItem.emit(name) | 5410 self.completeRepopulateItem.emit(name) |
5043 | 5411 |
5044 ############################################################## | 5412 ############################################################## |
5045 ## Below is the VCS interface | 5413 ## Below is the VCS interface |
5046 ############################################################## | 5414 ############################################################## |
5047 | 5415 |
5048 def initVCS(self, vcsSystem=None, nooverride=False): | 5416 def initVCS(self, vcsSystem=None, nooverride=False): |
5049 """ | 5417 """ |
5050 Public method used to instantiate a vcs system. | 5418 Public method used to instantiate a vcs system. |
5051 | 5419 |
5052 @param vcsSystem type of VCS to be used (string) | 5420 @param vcsSystem type of VCS to be used (string) |
5053 @param nooverride flag indicating to ignore an override request | 5421 @param nooverride flag indicating to ignore an override request |
5054 (boolean) | 5422 (boolean) |
5055 @return a reference to the vcs object | 5423 @return a reference to the vcs object |
5056 """ | 5424 """ |
5057 vcs = None | 5425 vcs = None |
5058 forProject = True | 5426 forProject = True |
5059 override = False | 5427 override = False |
5060 | 5428 |
5061 if vcsSystem is None: | 5429 if vcsSystem is None: |
5062 if self.pdata["VCS"] and self.pdata["VCS"] != 'None': | 5430 if self.pdata["VCS"] and self.pdata["VCS"] != "None": |
5063 vcsSystem = self.pdata["VCS"] | 5431 vcsSystem = self.pdata["VCS"] |
5064 else: | 5432 else: |
5065 forProject = False | 5433 forProject = False |
5066 | 5434 |
5067 if ( | 5435 if ( |
5068 forProject and | 5436 forProject |
5069 self.pdata["VCS"] and | 5437 and self.pdata["VCS"] |
5070 self.pdata["VCS"] != 'None' and | 5438 and self.pdata["VCS"] != "None" |
5071 self.pudata["VCSOVERRIDE"] and | 5439 and self.pudata["VCSOVERRIDE"] |
5072 not nooverride | 5440 and not nooverride |
5073 ): | 5441 ): |
5074 vcsSystem = self.pudata["VCSOVERRIDE"] | 5442 vcsSystem = self.pudata["VCSOVERRIDE"] |
5075 override = True | 5443 override = True |
5076 | 5444 |
5077 if vcsSystem is not None: | 5445 if vcsSystem is not None: |
5078 import VCS | 5446 import VCS |
5447 | |
5079 try: | 5448 try: |
5080 vcs = VCS.factory(vcsSystem) | 5449 vcs = VCS.factory(vcsSystem) |
5081 except ImportError: | 5450 except ImportError: |
5082 if override: | 5451 if override: |
5083 # override failed, revert to original | 5452 # override failed, revert to original |
5084 self.pudata["VCSOVERRIDE"] = "" | 5453 self.pudata["VCSOVERRIDE"] = "" |
5085 return self.initVCS(nooverride=True) | 5454 return self.initVCS(nooverride=True) |
5086 | 5455 |
5087 if vcs: | 5456 if vcs: |
5088 vcsExists, msg = vcs.vcsExists() | 5457 vcsExists, msg = vcs.vcsExists() |
5089 if not vcsExists: | 5458 if not vcsExists: |
5090 if override: | 5459 if override: |
5091 # override failed, revert to original | 5460 # override failed, revert to original |
5094 self.ui, | 5463 self.ui, |
5095 self.tr("Version Control System"), | 5464 self.tr("Version Control System"), |
5096 self.tr( | 5465 self.tr( |
5097 "<p>The selected VCS <b>{0}</b> could not be" | 5466 "<p>The selected VCS <b>{0}</b> could not be" |
5098 " found. <br/>Reverting override.</p><p>{1}" | 5467 " found. <br/>Reverting override.</p><p>{1}" |
5099 "</p>") | 5468 "</p>" |
5100 .format(vcsSystem, msg)) | 5469 ).format(vcsSystem, msg), |
5470 ) | |
5101 self.pudata["VCSOVERRIDE"] = "" | 5471 self.pudata["VCSOVERRIDE"] = "" |
5102 return self.initVCS(nooverride=True) | 5472 return self.initVCS(nooverride=True) |
5103 | 5473 |
5104 with EricOverridenCursor(): | 5474 with EricOverridenCursor(): |
5105 EricMessageBox.critical( | 5475 EricMessageBox.critical( |
5106 self.ui, | 5476 self.ui, |
5107 self.tr("Version Control System"), | 5477 self.tr("Version Control System"), |
5108 self.tr( | 5478 self.tr( |
5109 "<p>The selected VCS <b>{0}</b> could not be" | 5479 "<p>The selected VCS <b>{0}</b> could not be" |
5110 " found.<br/>Disabling version control.</p>" | 5480 " found.<br/>Disabling version control.</p>" |
5111 "<p>{1}</p>").format(vcsSystem, msg)) | 5481 "<p>{1}</p>" |
5482 ).format(vcsSystem, msg), | |
5483 ) | |
5112 vcs = None | 5484 vcs = None |
5113 if forProject: | 5485 if forProject: |
5114 self.pdata["VCS"] = 'None' | 5486 self.pdata["VCS"] = "None" |
5115 self.setDirty(True) | 5487 self.setDirty(True) |
5116 else: | 5488 else: |
5117 vcs.vcsInitConfig(self) | 5489 vcs.vcsInitConfig(self) |
5118 | 5490 |
5119 if vcs and forProject: | 5491 if vcs and forProject: |
5120 # set the vcs options | 5492 # set the vcs options |
5121 if vcs.vcsSupportCommandOptions(): | 5493 if vcs.vcsSupportCommandOptions(): |
5122 with contextlib.suppress(LookupError): | 5494 with contextlib.suppress(LookupError): |
5123 vcsopt = copy.deepcopy(self.pdata["VCSOPTIONS"]) | 5495 vcsopt = copy.deepcopy(self.pdata["VCSOPTIONS"]) |
5124 vcs.vcsSetOptions(vcsopt) | 5496 vcs.vcsSetOptions(vcsopt) |
5125 # set vcs specific data | 5497 # set vcs specific data |
5126 with contextlib.suppress(LookupError): | 5498 with contextlib.suppress(LookupError): |
5127 vcsother = copy.deepcopy(self.pdata["VCSOTHERDATA"]) | 5499 vcsother = copy.deepcopy(self.pdata["VCSOTHERDATA"]) |
5128 vcs.vcsSetOtherData(vcsother) | 5500 vcs.vcsSetOtherData(vcsother) |
5129 | 5501 |
5130 if forProject: | 5502 if forProject: |
5131 if vcs is None: | 5503 if vcs is None: |
5132 import VCS | 5504 import VCS |
5505 | |
5133 self.vcsProjectHelper = VCS.getBasicHelper(self) | 5506 self.vcsProjectHelper = VCS.getBasicHelper(self) |
5134 self.vcsBasicHelper = True | 5507 self.vcsBasicHelper = True |
5135 else: | 5508 else: |
5136 self.vcsProjectHelper = vcs.vcsGetProjectHelper(self) | 5509 self.vcsProjectHelper = vcs.vcsGetProjectHelper(self) |
5137 self.vcsBasicHelper = False | 5510 self.vcsBasicHelper = False |
5138 if self.vcsMenu is not None: | 5511 if self.vcsMenu is not None: |
5139 self.vcsProjectHelper.initMenu(self.vcsMenu) | 5512 self.vcsProjectHelper.initMenu(self.vcsMenu) |
5140 self.vcsMenu.setEnabled(self.vcsSoftwareAvailable()) | 5513 self.vcsMenu.setEnabled(self.vcsSoftwareAvailable()) |
5141 | 5514 |
5142 return vcs | 5515 return vcs |
5143 | 5516 |
5144 def resetVCS(self): | 5517 def resetVCS(self): |
5145 """ | 5518 """ |
5146 Public method to reset the VCS. | 5519 Public method to reset the VCS. |
5147 """ | 5520 """ |
5148 self.pdata["VCS"] = 'None' | 5521 self.pdata["VCS"] = "None" |
5149 self.vcs = self.initVCS() | 5522 self.vcs = self.initVCS() |
5150 ericApp().getObject("PluginManager").deactivateVcsPlugins() | 5523 ericApp().getObject("PluginManager").deactivateVcsPlugins() |
5151 | 5524 |
5152 def __showContextMenuVCS(self): | 5525 def __showContextMenuVCS(self): |
5153 """ | 5526 """ |
5154 Private slot called before the vcs menu is shown. | 5527 Private slot called before the vcs menu is shown. |
5155 """ | 5528 """ |
5156 self.vcsProjectHelper.showMenu() | 5529 self.vcsProjectHelper.showMenu() |
5157 if self.vcsBasicHelper: | 5530 if self.vcsBasicHelper: |
5158 self.showMenu.emit("VCS", self.vcsMenu) | 5531 self.showMenu.emit("VCS", self.vcsMenu) |
5159 | 5532 |
5160 def vcsSoftwareAvailable(self): | 5533 def vcsSoftwareAvailable(self): |
5161 """ | 5534 """ |
5162 Public method to check, if some supported VCS software is available | 5535 Public method to check, if some supported VCS software is available |
5163 to the IDE. | 5536 to the IDE. |
5164 | 5537 |
5165 @return flag indicating availability of VCS software (boolean) | 5538 @return flag indicating availability of VCS software (boolean) |
5166 """ | 5539 """ |
5167 vcsSystemsDict = ( | 5540 vcsSystemsDict = ( |
5168 ericApp().getObject("PluginManager") | 5541 ericApp() |
5542 .getObject("PluginManager") | |
5169 .getPluginDisplayStrings("version_control") | 5543 .getPluginDisplayStrings("version_control") |
5170 ) | 5544 ) |
5171 return len(vcsSystemsDict) != 0 | 5545 return len(vcsSystemsDict) != 0 |
5172 | 5546 |
5173 def __vcsStatusChanged(self): | 5547 def __vcsStatusChanged(self): |
5174 """ | 5548 """ |
5175 Private slot to handle a change of the overall VCS status. | 5549 Private slot to handle a change of the overall VCS status. |
5176 """ | 5550 """ |
5177 self.projectChanged.emit() | 5551 self.projectChanged.emit() |
5178 | 5552 |
5179 def __vcsConnectStatusMonitor(self): | 5553 def __vcsConnectStatusMonitor(self): |
5180 """ | 5554 """ |
5181 Private method to start the VCS monitor and connect its signals. | 5555 Private method to start the VCS monitor and connect its signals. |
5182 """ | 5556 """ |
5183 if self.vcs is not None: | 5557 if self.vcs is not None: |
5184 self.vcs.committed.connect(self.vcsCommitted) | 5558 self.vcs.committed.connect(self.vcsCommitted) |
5185 | 5559 |
5186 self.vcs.startStatusMonitor(self) | 5560 self.vcs.startStatusMonitor(self) |
5187 self.vcs.vcsStatusMonitorData.connect( | 5561 self.vcs.vcsStatusMonitorData.connect(self.__model.changeVCSStates) |
5188 self.__model.changeVCSStates) | 5562 self.vcs.vcsStatusMonitorData.connect(self.vcsStatusMonitorData) |
5189 self.vcs.vcsStatusMonitorData.connect( | 5563 self.vcs.vcsStatusMonitorAllData.connect(self.vcsStatusMonitorAllData) |
5190 self.vcsStatusMonitorData) | 5564 self.vcs.vcsStatusMonitorStatus.connect(self.vcsStatusMonitorStatus) |
5191 self.vcs.vcsStatusMonitorAllData.connect( | 5565 self.vcs.vcsStatusMonitorInfo.connect(self.vcsStatusMonitorInfo) |
5192 self.vcsStatusMonitorAllData) | 5566 self.vcs.vcsStatusChanged.connect(self.__vcsStatusChanged) |
5193 self.vcs.vcsStatusMonitorStatus.connect( | 5567 |
5194 self.vcsStatusMonitorStatus) | |
5195 self.vcs.vcsStatusMonitorInfo.connect( | |
5196 self.vcsStatusMonitorInfo) | |
5197 self.vcs.vcsStatusChanged.connect( | |
5198 self.__vcsStatusChanged) | |
5199 | |
5200 ######################################################################### | 5568 ######################################################################### |
5201 ## Below is the interface to the checker tools | 5569 ## Below is the interface to the checker tools |
5202 ######################################################################### | 5570 ######################################################################### |
5203 | 5571 |
5204 def __showContextMenuChecks(self): | 5572 def __showContextMenuChecks(self): |
5205 """ | 5573 """ |
5206 Private slot called before the checks menu is shown. | 5574 Private slot called before the checks menu is shown. |
5207 """ | 5575 """ |
5208 self.showMenu.emit("Checks", self.checksMenu) | 5576 self.showMenu.emit("Checks", self.checksMenu) |
5209 | 5577 |
5210 ######################################################################### | 5578 ######################################################################### |
5211 ## Below is the interface to the packagers tools | 5579 ## Below is the interface to the packagers tools |
5212 ######################################################################### | 5580 ######################################################################### |
5213 | 5581 |
5214 def __showContextMenuPackagers(self): | 5582 def __showContextMenuPackagers(self): |
5215 """ | 5583 """ |
5216 Private slot called before the packagers menu is shown. | 5584 Private slot called before the packagers menu is shown. |
5217 """ | 5585 """ |
5218 self.showMenu.emit("Packagers", self.packagersMenu) | 5586 self.showMenu.emit("Packagers", self.packagersMenu) |
5219 | 5587 |
5220 ######################################################################### | 5588 ######################################################################### |
5221 ## Below is the interface to the apidoc tools | 5589 ## Below is the interface to the apidoc tools |
5222 ######################################################################### | 5590 ######################################################################### |
5223 | 5591 |
5224 def __showContextMenuApiDoc(self): | 5592 def __showContextMenuApiDoc(self): |
5225 """ | 5593 """ |
5226 Private slot called before the apidoc menu is shown. | 5594 Private slot called before the apidoc menu is shown. |
5227 """ | 5595 """ |
5228 self.showMenu.emit("Apidoc", self.apidocMenu) | 5596 self.showMenu.emit("Apidoc", self.apidocMenu) |
5229 | 5597 |
5230 ######################################################################### | 5598 ######################################################################### |
5231 ## Below is the interface to the show tools | 5599 ## Below is the interface to the show tools |
5232 ######################################################################### | 5600 ######################################################################### |
5233 | 5601 |
5234 def __showCodeMetrics(self): | 5602 def __showCodeMetrics(self): |
5235 """ | 5603 """ |
5236 Private slot used to calculate some code metrics for the project files. | 5604 Private slot used to calculate some code metrics for the project files. |
5237 """ | 5605 """ |
5238 files = [os.path.join(self.ppath, file) | 5606 files = [ |
5239 for file in self.pdata["SOURCES"] if file.endswith(".py")] | 5607 os.path.join(self.ppath, file) |
5608 for file in self.pdata["SOURCES"] | |
5609 if file.endswith(".py") | |
5610 ] | |
5240 from DataViews.CodeMetricsDialog import CodeMetricsDialog | 5611 from DataViews.CodeMetricsDialog import CodeMetricsDialog |
5612 | |
5241 self.codemetrics = CodeMetricsDialog() | 5613 self.codemetrics = CodeMetricsDialog() |
5242 self.codemetrics.show() | 5614 self.codemetrics.show() |
5243 self.codemetrics.prepare(files) | 5615 self.codemetrics.prepare(files) |
5244 | 5616 |
5245 def __showCodeCoverage(self): | 5617 def __showCodeCoverage(self): |
5252 EricMessageBox.critical( | 5624 EricMessageBox.critical( |
5253 self.ui, | 5625 self.ui, |
5254 self.tr("Coverage Data"), | 5626 self.tr("Coverage Data"), |
5255 self.tr( | 5627 self.tr( |
5256 "There is no main script defined for the" | 5628 "There is no main script defined for the" |
5257 " current project. Aborting")) | 5629 " current project. Aborting" |
5630 ), | |
5631 ) | |
5258 return | 5632 return |
5259 | 5633 |
5260 files = Utilities.getCoverageFileNames(fn) | 5634 files = Utilities.getCoverageFileNames(fn) |
5261 if files: | 5635 if files: |
5262 if len(files) > 1: | 5636 if len(files) > 1: |
5263 fn, ok = QInputDialog.getItem( | 5637 fn, ok = QInputDialog.getItem( |
5264 None, | 5638 None, |
5265 self.tr("Code Coverage"), | 5639 self.tr("Code Coverage"), |
5266 self.tr("Please select a coverage file"), | 5640 self.tr("Please select a coverage file"), |
5267 files, | 5641 files, |
5268 0, False) | 5642 0, |
5643 False, | |
5644 ) | |
5269 if not ok: | 5645 if not ok: |
5270 return | 5646 return |
5271 else: | 5647 else: |
5272 fn = files[0] | 5648 fn = files[0] |
5273 else: | 5649 else: |
5274 return | 5650 return |
5275 | 5651 |
5276 files = [os.path.join(self.ppath, file) | 5652 files = [ |
5277 for file in self.pdata["SOURCES"] | 5653 os.path.join(self.ppath, file) |
5278 if os.path.splitext(file)[1].startswith(".py")] | 5654 for file in self.pdata["SOURCES"] |
5655 if os.path.splitext(file)[1].startswith(".py") | |
5656 ] | |
5279 from DataViews.PyCoverageDialog import PyCoverageDialog | 5657 from DataViews.PyCoverageDialog import PyCoverageDialog |
5658 | |
5280 self.codecoverage = PyCoverageDialog() | 5659 self.codecoverage = PyCoverageDialog() |
5281 self.codecoverage.show() | 5660 self.codecoverage.show() |
5282 self.codecoverage.start(fn, files) | 5661 self.codecoverage.start(fn, files) |
5283 | 5662 |
5284 def __showProfileData(self): | 5663 def __showProfileData(self): |
5290 EricMessageBox.critical( | 5669 EricMessageBox.critical( |
5291 self.ui, | 5670 self.ui, |
5292 self.tr("Profile Data"), | 5671 self.tr("Profile Data"), |
5293 self.tr( | 5672 self.tr( |
5294 "There is no main script defined for the" | 5673 "There is no main script defined for the" |
5295 " current project. Aborting")) | 5674 " current project. Aborting" |
5675 ), | |
5676 ) | |
5296 return | 5677 return |
5297 | 5678 |
5298 files = Utilities.getProfileFileNames(fn) | 5679 files = Utilities.getProfileFileNames(fn) |
5299 if files: | 5680 if files: |
5300 if len(files) > 1: | 5681 if len(files) > 1: |
5301 fn, ok = QInputDialog.getItem( | 5682 fn, ok = QInputDialog.getItem( |
5302 None, | 5683 None, |
5303 self.tr("Profile Data"), | 5684 self.tr("Profile Data"), |
5304 self.tr("Please select a profile file"), | 5685 self.tr("Please select a profile file"), |
5305 files, | 5686 files, |
5306 0, False) | 5687 0, |
5688 False, | |
5689 ) | |
5307 if not ok: | 5690 if not ok: |
5308 return | 5691 return |
5309 else: | 5692 else: |
5310 fn = files[0] | 5693 fn = files[0] |
5311 else: | 5694 else: |
5312 return | 5695 return |
5313 | 5696 |
5314 from DataViews.PyProfileDialog import PyProfileDialog | 5697 from DataViews.PyProfileDialog import PyProfileDialog |
5698 | |
5315 self.profiledata = PyProfileDialog() | 5699 self.profiledata = PyProfileDialog() |
5316 self.profiledata.show() | 5700 self.profiledata.show() |
5317 self.profiledata.start(fn) | 5701 self.profiledata.start(fn) |
5318 | 5702 |
5319 def __showContextMenuShow(self): | 5703 def __showContextMenuShow(self): |
5320 """ | 5704 """ |
5321 Private slot called before the show menu is shown. | 5705 Private slot called before the show menu is shown. |
5322 """ | 5706 """ |
5323 fn = self.getMainScript(True) | 5707 fn = self.getMainScript(True) |
5324 if not fn: | 5708 if not fn: |
5325 fn = self.getProjectPath() | 5709 fn = self.getProjectPath() |
5326 | 5710 |
5327 self.codeProfileAct.setEnabled( | 5711 self.codeProfileAct.setEnabled( |
5328 self.isPy3Project() and | 5712 self.isPy3Project() and bool(Utilities.getProfileFileName(fn)) |
5329 bool(Utilities.getProfileFileName(fn)) | |
5330 ) | 5713 ) |
5331 self.codeCoverageAct.setEnabled( | 5714 self.codeCoverageAct.setEnabled( |
5332 self.isPy3Project() and | 5715 self.isPy3Project() and bool(Utilities.getCoverageFileNames(fn)) |
5333 bool(Utilities.getCoverageFileNames(fn)) | 5716 ) |
5334 ) | 5717 |
5335 | |
5336 self.showMenu.emit("Show", self.menuShow) | 5718 self.showMenu.emit("Show", self.menuShow) |
5337 | 5719 |
5338 ######################################################################### | 5720 ######################################################################### |
5339 ## Below is the interface to the diagrams | 5721 ## Below is the interface to the diagrams |
5340 ######################################################################### | 5722 ######################################################################### |
5341 | 5723 |
5342 def __showContextMenuGraphics(self): | 5724 def __showContextMenuGraphics(self): |
5343 """ | 5725 """ |
5344 Private slot called before the graphics menu is shown. | 5726 Private slot called before the graphics menu is shown. |
5345 """ | 5727 """ |
5346 self.showMenu.emit("Graphics", self.graphicsMenu) | 5728 self.showMenu.emit("Graphics", self.graphicsMenu) |
5347 | 5729 |
5348 def handleApplicationDiagram(self): | 5730 def handleApplicationDiagram(self): |
5349 """ | 5731 """ |
5350 Public method to handle the application diagram context menu action. | 5732 Public method to handle the application diagram context menu action. |
5351 """ | 5733 """ |
5352 res = EricMessageBox.yesNo( | 5734 res = EricMessageBox.yesNo( |
5353 self.ui, | 5735 self.ui, |
5354 self.tr("Application Diagram"), | 5736 self.tr("Application Diagram"), |
5355 self.tr("""Include module names?"""), | 5737 self.tr("""Include module names?"""), |
5356 yesDefault=True) | 5738 yesDefault=True, |
5357 | 5739 ) |
5740 | |
5358 from Graphics.UMLDialog import UMLDialog, UMLDialogType | 5741 from Graphics.UMLDialog import UMLDialog, UMLDialogType |
5742 | |
5359 self.applicationDiagram = UMLDialog( | 5743 self.applicationDiagram = UMLDialog( |
5360 UMLDialogType.APPLICATION_DIAGRAM, self, self.parent(), | 5744 UMLDialogType.APPLICATION_DIAGRAM, self, self.parent(), noModules=not res |
5361 noModules=not res) | 5745 ) |
5362 self.applicationDiagram.show() | 5746 self.applicationDiagram.show() |
5363 | 5747 |
5364 def __loadDiagram(self): | 5748 def __loadDiagram(self): |
5365 """ | 5749 """ |
5366 Private slot to load a diagram from file. | 5750 Private slot to load a diagram from file. |
5367 """ | 5751 """ |
5368 from Graphics.UMLDialog import UMLDialog, UMLDialogType | 5752 from Graphics.UMLDialog import UMLDialog, UMLDialogType |
5753 | |
5369 self.loadedDiagram = None | 5754 self.loadedDiagram = None |
5370 loadedDiagram = UMLDialog(UMLDialogType.NO_DIAGRAM, | 5755 loadedDiagram = UMLDialog(UMLDialogType.NO_DIAGRAM, self, parent=self.parent()) |
5371 self, parent=self.parent()) | |
5372 if loadedDiagram.load(): | 5756 if loadedDiagram.load(): |
5373 self.loadedDiagram = loadedDiagram | 5757 self.loadedDiagram = loadedDiagram |
5374 self.loadedDiagram.show(fromFile=True) | 5758 self.loadedDiagram.show(fromFile=True) |
5375 | 5759 |
5376 ######################################################################### | 5760 ######################################################################### |
5377 ## Below is the interface to the VCS monitor thread | 5761 ## Below is the interface to the VCS monitor thread |
5378 ######################################################################### | 5762 ######################################################################### |
5379 | 5763 |
5380 def setStatusMonitorInterval(self, interval): | 5764 def setStatusMonitorInterval(self, interval): |
5381 """ | 5765 """ |
5382 Public method to se the interval of the VCS status monitor thread. | 5766 Public method to se the interval of the VCS status monitor thread. |
5383 | 5767 |
5384 @param interval status monitor interval in seconds (integer) | 5768 @param interval status monitor interval in seconds (integer) |
5385 """ | 5769 """ |
5386 if self.vcs is not None: | 5770 if self.vcs is not None: |
5387 self.vcs.setStatusMonitorInterval(interval, self) | 5771 self.vcs.setStatusMonitorInterval(interval, self) |
5388 | 5772 |
5389 def getStatusMonitorInterval(self): | 5773 def getStatusMonitorInterval(self): |
5390 """ | 5774 """ |
5391 Public method to get the monitor interval. | 5775 Public method to get the monitor interval. |
5392 | 5776 |
5393 @return interval in seconds (integer) | 5777 @return interval in seconds (integer) |
5394 """ | 5778 """ |
5395 if self.vcs is not None: | 5779 if self.vcs is not None: |
5396 return self.vcs.getStatusMonitorInterval() | 5780 return self.vcs.getStatusMonitorInterval() |
5397 else: | 5781 else: |
5398 return 0 | 5782 return 0 |
5399 | 5783 |
5400 def setStatusMonitorAutoUpdate(self, auto): | 5784 def setStatusMonitorAutoUpdate(self, auto): |
5401 """ | 5785 """ |
5402 Public method to enable the auto update function. | 5786 Public method to enable the auto update function. |
5403 | 5787 |
5404 @param auto status of the auto update function (boolean) | 5788 @param auto status of the auto update function (boolean) |
5405 """ | 5789 """ |
5406 if self.vcs is not None: | 5790 if self.vcs is not None: |
5407 self.vcs.setStatusMonitorAutoUpdate(auto) | 5791 self.vcs.setStatusMonitorAutoUpdate(auto) |
5408 | 5792 |
5409 def getStatusMonitorAutoUpdate(self): | 5793 def getStatusMonitorAutoUpdate(self): |
5410 """ | 5794 """ |
5411 Public method to retrieve the status of the auto update function. | 5795 Public method to retrieve the status of the auto update function. |
5412 | 5796 |
5413 @return status of the auto update function (boolean) | 5797 @return status of the auto update function (boolean) |
5414 """ | 5798 """ |
5415 if self.vcs is not None: | 5799 if self.vcs is not None: |
5416 return self.vcs.getStatusMonitorAutoUpdate() | 5800 return self.vcs.getStatusMonitorAutoUpdate() |
5417 else: | 5801 else: |
5418 return False | 5802 return False |
5419 | 5803 |
5420 def checkVCSStatus(self): | 5804 def checkVCSStatus(self): |
5421 """ | 5805 """ |
5422 Public method to wake up the VCS status monitor thread. | 5806 Public method to wake up the VCS status monitor thread. |
5423 """ | 5807 """ |
5424 if self.vcs is not None: | 5808 if self.vcs is not None: |
5425 self.vcs.checkVCSStatus() | 5809 self.vcs.checkVCSStatus() |
5426 | 5810 |
5427 def clearStatusMonitorCachedState(self, name): | 5811 def clearStatusMonitorCachedState(self, name): |
5428 """ | 5812 """ |
5429 Public method to clear the cached VCS state of a file/directory. | 5813 Public method to clear the cached VCS state of a file/directory. |
5430 | 5814 |
5431 @param name name of the entry to be cleared (string) | 5815 @param name name of the entry to be cleared (string) |
5432 """ | 5816 """ |
5433 if self.vcs is not None: | 5817 if self.vcs is not None: |
5434 self.vcs.clearStatusMonitorCachedState(name) | 5818 self.vcs.clearStatusMonitorCachedState(name) |
5435 | 5819 |
5436 def startStatusMonitor(self): | 5820 def startStatusMonitor(self): |
5437 """ | 5821 """ |
5438 Public method to start the VCS status monitor thread. | 5822 Public method to start the VCS status monitor thread. |
5439 """ | 5823 """ |
5440 if self.vcs is not None: | 5824 if self.vcs is not None: |
5441 self.vcs.startStatusMonitor(self) | 5825 self.vcs.startStatusMonitor(self) |
5442 | 5826 |
5443 def stopStatusMonitor(self): | 5827 def stopStatusMonitor(self): |
5444 """ | 5828 """ |
5445 Public method to stop the VCS status monitor thread. | 5829 Public method to stop the VCS status monitor thread. |
5446 """ | 5830 """ |
5447 if self.vcs is not None: | 5831 if self.vcs is not None: |
5448 self.vcs.stopStatusMonitor() | 5832 self.vcs.stopStatusMonitor() |
5449 | 5833 |
5450 ######################################################################### | 5834 ######################################################################### |
5451 ## Below are the plugin development related methods | 5835 ## Below are the plugin development related methods |
5452 ######################################################################### | 5836 ######################################################################### |
5453 | 5837 |
5454 def __pluginVersionToTuple(self, versionStr): | 5838 def __pluginVersionToTuple(self, versionStr): |
5455 """ | 5839 """ |
5456 Private method to convert a plug-in version string into a version | 5840 Private method to convert a plug-in version string into a version |
5457 tuple. | 5841 tuple. |
5458 | 5842 |
5459 @param versionStr version string to be converted | 5843 @param versionStr version string to be converted |
5460 @type str | 5844 @type str |
5461 @return version info as a tuple | 5845 @return version info as a tuple |
5462 @rtype tuple of int and str | 5846 @rtype tuple of int and str |
5463 """ | 5847 """ |
5469 for part in versionStr.split("."): | 5853 for part in versionStr.split("."): |
5470 try: | 5854 try: |
5471 vParts.append(int(part)) | 5855 vParts.append(int(part)) |
5472 except ValueError: | 5856 except ValueError: |
5473 vParts.append(part) | 5857 vParts.append(part) |
5474 | 5858 |
5475 if additional: | 5859 if additional: |
5476 vParts.append(additional) | 5860 vParts.append(additional) |
5477 | 5861 |
5478 return tuple(vParts) | 5862 return tuple(vParts) |
5479 | 5863 |
5480 def __pluginCreatePkgList(self): | 5864 def __pluginCreatePkgList(self): |
5481 """ | 5865 """ |
5482 Private slot to create a PKGLIST file needed for archive file creation. | 5866 Private slot to create a PKGLIST file needed for archive file creation. |
5483 """ | 5867 """ |
5484 pkglist = os.path.join(self.ppath, "PKGLIST") | 5868 pkglist = os.path.join(self.ppath, "PKGLIST") |
5486 res = EricMessageBox.yesNo( | 5870 res = EricMessageBox.yesNo( |
5487 self.ui, | 5871 self.ui, |
5488 self.tr("Create Package List"), | 5872 self.tr("Create Package List"), |
5489 self.tr( | 5873 self.tr( |
5490 "<p>The file <b>PKGLIST</b> already" | 5874 "<p>The file <b>PKGLIST</b> already" |
5491 " exists.</p><p>Overwrite it?</p>"), | 5875 " exists.</p><p>Overwrite it?</p>" |
5492 icon=EricMessageBox.Warning) | 5876 ), |
5877 icon=EricMessageBox.Warning, | |
5878 ) | |
5493 if not res: | 5879 if not res: |
5494 return # don't overwrite | 5880 return # don't overwrite |
5495 | 5881 |
5496 # build the list of entries | 5882 # build the list of entries |
5497 lst_ = [] | 5883 lst_ = [] |
5498 for key in ["SOURCES", "FORMS", "RESOURCES", "TRANSLATIONS", | 5884 for key in [ |
5499 "INTERFACES", "PROTOCOLS", "OTHERS"]: | 5885 "SOURCES", |
5886 "FORMS", | |
5887 "RESOURCES", | |
5888 "TRANSLATIONS", | |
5889 "INTERFACES", | |
5890 "PROTOCOLS", | |
5891 "OTHERS", | |
5892 ]: | |
5500 lst_.extend(self.pdata[key]) | 5893 lst_.extend(self.pdata[key]) |
5501 lst = [] | 5894 lst = [] |
5502 for entry in lst_: | 5895 for entry in lst_: |
5503 if os.path.isdir(self.getAbsolutePath(entry)): | 5896 if os.path.isdir(self.getAbsolutePath(entry)): |
5504 lst.extend( | 5897 lst.extend( |
5505 [self.getRelativePath(p) for p in | 5898 [ |
5506 Utilities.direntries(self.getAbsolutePath(entry), True)]) | 5899 self.getRelativePath(p) |
5900 for p in Utilities.direntries(self.getAbsolutePath(entry), True) | |
5901 ] | |
5902 ) | |
5507 continue | 5903 continue |
5508 else: | 5904 else: |
5509 lst.append(entry) | 5905 lst.append(entry) |
5510 lst.sort() | 5906 lst.sort() |
5511 if "PKGLIST" in lst: | 5907 if "PKGLIST" in lst: |
5512 lst.remove("PKGLIST") | 5908 lst.remove("PKGLIST") |
5513 | 5909 |
5514 # build the header to indicate a freshly generated list | 5910 # build the header to indicate a freshly generated list |
5515 header = [ | 5911 header = [ |
5516 ";", | 5912 ";", |
5517 "; initial_list (REMOVE THIS LINE WHEN DONE)", | 5913 "; initial_list (REMOVE THIS LINE WHEN DONE)", |
5518 ";", | 5914 ";", |
5519 " ", | 5915 " ", |
5520 ] | 5916 ] |
5521 | 5917 |
5522 # write the file | 5918 # write the file |
5523 try: | 5919 try: |
5524 newline = None if self.pdata["EOL"] == 0 else self.getEolString() | 5920 newline = None if self.pdata["EOL"] == 0 else self.getEolString() |
5525 with open(pkglist, "w", encoding="utf-8", | 5921 with open(pkglist, "w", encoding="utf-8", newline=newline) as pkglistFile: |
5526 newline=newline) as pkglistFile: | |
5527 pkglistFile.write("\n".join(header) + "\n") | 5922 pkglistFile.write("\n".join(header) + "\n") |
5528 pkglistFile.write( | 5923 pkglistFile.write( |
5529 "\n".join([Utilities.fromNativeSeparators(f) | 5924 "\n".join([Utilities.fromNativeSeparators(f) for f in lst]) |
5530 for f in lst])) | 5925 ) |
5531 pkglistFile.write("\n") | 5926 pkglistFile.write("\n") |
5532 # ensure the file ends with an empty line | 5927 # ensure the file ends with an empty line |
5533 except OSError as why: | 5928 except OSError as why: |
5534 EricMessageBox.critical( | 5929 EricMessageBox.critical( |
5535 self.ui, | 5930 self.ui, |
5536 self.tr("Create Package List"), | 5931 self.tr("Create Package List"), |
5537 self.tr( | 5932 self.tr( |
5538 """<p>The file <b>PKGLIST</b> could not be created.</p>""" | 5933 """<p>The file <b>PKGLIST</b> could not be created.</p>""" |
5539 """<p>Reason: {0}</p>""").format(str(why))) | 5934 """<p>Reason: {0}</p>""" |
5935 ).format(str(why)), | |
5936 ) | |
5540 return | 5937 return |
5541 | 5938 |
5542 if "PKGLIST" not in self.pdata["OTHERS"]: | 5939 if "PKGLIST" not in self.pdata["OTHERS"]: |
5543 self.appendFile("PKGLIST") | 5940 self.appendFile("PKGLIST") |
5544 | 5941 |
5545 @pyqtSlot() | 5942 @pyqtSlot() |
5546 def __pluginCreateArchives(self, snapshot=False): | 5943 def __pluginCreateArchives(self, snapshot=False): |
5547 """ | 5944 """ |
5548 Private slot to create eric plugin archives. | 5945 Private slot to create eric plugin archives. |
5549 | 5946 |
5550 @param snapshot flag indicating snapshot archives (boolean) | 5947 @param snapshot flag indicating snapshot archives (boolean) |
5551 """ | 5948 """ |
5552 if not self.pdata["MAINSCRIPT"]: | 5949 if not self.pdata["MAINSCRIPT"]: |
5553 EricMessageBox.critical( | 5950 EricMessageBox.critical( |
5554 self.ui, | 5951 self.ui, |
5555 self.tr("Create Plugin Archive"), | 5952 self.tr("Create Plugin Archive"), |
5556 self.tr( | 5953 self.tr( |
5557 """The project does not have a main script defined. """ | 5954 """The project does not have a main script defined. """ |
5558 """Aborting...""")) | 5955 """Aborting...""" |
5956 ), | |
5957 ) | |
5559 return | 5958 return |
5560 | 5959 |
5561 selectedLists = [] | 5960 selectedLists = [] |
5562 pkglists = [os.path.basename(f) for f in | 5961 pkglists = [ |
5563 glob.glob(os.path.join(self.ppath, "PKGLIST*"))] | 5962 os.path.basename(f) for f in glob.glob(os.path.join(self.ppath, "PKGLIST*")) |
5963 ] | |
5564 if len(pkglists) == 1: | 5964 if len(pkglists) == 1: |
5565 selectedLists = [os.path.join(self.ppath, pkglists[0])] | 5965 selectedLists = [os.path.join(self.ppath, pkglists[0])] |
5566 elif len(pkglists) > 1: | 5966 elif len(pkglists) > 1: |
5567 dlg = EricListSelectionDialog( | 5967 dlg = EricListSelectionDialog( |
5568 sorted(pkglists), title=self.tr("Create Plugin Archive"), | 5968 sorted(pkglists), |
5969 title=self.tr("Create Plugin Archive"), | |
5569 message=self.tr("Select package lists:"), | 5970 message=self.tr("Select package lists:"), |
5570 checkBoxSelection=True) | 5971 checkBoxSelection=True, |
5972 ) | |
5571 if dlg.exec() == QDialog.DialogCode.Accepted: | 5973 if dlg.exec() == QDialog.DialogCode.Accepted: |
5572 selectedLists = [os.path.join(self.ppath, s) | 5974 selectedLists = [ |
5573 for s in dlg.getSelection()] | 5975 os.path.join(self.ppath, s) for s in dlg.getSelection() |
5976 ] | |
5574 else: | 5977 else: |
5575 return | 5978 return |
5576 | 5979 |
5577 if not selectedLists: | 5980 if not selectedLists: |
5578 EricMessageBox.critical( | 5981 EricMessageBox.critical( |
5579 self.ui, | 5982 self.ui, |
5580 self.tr("Create Plugin Archive"), | 5983 self.tr("Create Plugin Archive"), |
5581 self.tr("""<p>No package list files (PKGLIST*) available or""" | 5984 self.tr( |
5582 """ selected. Aborting...</p>""")) | 5985 """<p>No package list files (PKGLIST*) available or""" |
5986 """ selected. Aborting...</p>""" | |
5987 ), | |
5988 ) | |
5583 return | 5989 return |
5584 | 5990 |
5585 progress = EricProgressDialog( | 5991 progress = EricProgressDialog( |
5586 self.tr("Creating plugin archives..."), self.tr("Abort"), | 5992 self.tr("Creating plugin archives..."), |
5587 0, len(selectedLists), self.tr("%v/%m Archives"), self.ui) | 5993 self.tr("Abort"), |
5994 0, | |
5995 len(selectedLists), | |
5996 self.tr("%v/%m Archives"), | |
5997 self.ui, | |
5998 ) | |
5588 progress.setMinimumDuration(0) | 5999 progress.setMinimumDuration(0) |
5589 progress.setWindowTitle(self.tr("Create Plugin Archives")) | 6000 progress.setWindowTitle(self.tr("Create Plugin Archives")) |
5590 errors = 0 | 6001 errors = 0 |
5591 for count, pkglist in enumerate(selectedLists): | 6002 for count, pkglist in enumerate(selectedLists): |
5592 progress.setValue(count) | 6003 progress.setValue(count) |
5593 if progress.wasCanceled(): | 6004 if progress.wasCanceled(): |
5594 break | 6005 break |
5595 | 6006 |
5596 try: | 6007 try: |
5597 with open(pkglist, "r", encoding="utf-8") as pkglistFile: | 6008 with open(pkglist, "r", encoding="utf-8") as pkglistFile: |
5598 names = pkglistFile.read() | 6009 names = pkglistFile.read() |
5599 except OSError as why: | 6010 except OSError as why: |
5600 EricMessageBox.critical( | 6011 EricMessageBox.critical( |
5601 self.ui, | 6012 self.ui, |
5602 self.tr("Create Plugin Archive"), | 6013 self.tr("Create Plugin Archive"), |
5603 self.tr( | 6014 self.tr( |
5604 """<p>The file <b>{0}</b> could not be read.</p>""" | 6015 """<p>The file <b>{0}</b> could not be read.</p>""" |
5605 """<p>Reason: {1}</p>""").format( | 6016 """<p>Reason: {1}</p>""" |
5606 os.path.basename(pkglist), str(why))) | 6017 ).format(os.path.basename(pkglist), str(why)), |
6018 ) | |
5607 errors += 1 | 6019 errors += 1 |
5608 continue | 6020 continue |
5609 | 6021 |
5610 lines = names.splitlines() | 6022 lines = names.splitlines() |
5611 archiveName = "" | 6023 archiveName = "" |
5612 archiveVersion = "" | 6024 archiveVersion = "" |
5613 names = [] | 6025 names = [] |
5614 listOK = True | 6026 listOK = True |
5629 self.tr("Create Plugin Archive"), | 6041 self.tr("Create Plugin Archive"), |
5630 self.tr( | 6042 self.tr( |
5631 """<p>The file <b>{0}</b> is not ready yet.""" | 6043 """<p>The file <b>{0}</b> is not ready yet.""" |
5632 """</p><p>Please rework it and delete the""" | 6044 """</p><p>Please rework it and delete the""" |
5633 """'; initial_list' line of the header.""" | 6045 """'; initial_list' line of the header.""" |
5634 """</p>""").format(os.path.basename(pkglist))) | 6046 """</p>""" |
6047 ).format(os.path.basename(pkglist)), | |
6048 ) | |
5635 errors += 1 | 6049 errors += 1 |
5636 listOK = False | 6050 listOK = False |
5637 break | 6051 break |
5638 elif line.strip(): | 6052 elif line.strip(): |
5639 names.append(line.strip()) | 6053 names.append(line.strip()) |
5640 | 6054 |
5641 if not listOK: | 6055 if not listOK: |
5642 continue | 6056 continue |
5643 | 6057 |
5644 names = sorted(names) | 6058 names = sorted(names) |
5645 archive = ( | 6059 archive = ( |
5646 os.path.join(self.ppath, archiveName) | 6060 os.path.join(self.ppath, archiveName) |
5647 if archiveName else | 6061 if archiveName |
5648 os.path.join(self.ppath, | 6062 else os.path.join( |
5649 self.pdata["MAINSCRIPT"].replace(".py", ".zip")) | 6063 self.ppath, self.pdata["MAINSCRIPT"].replace(".py", ".zip") |
6064 ) | |
5650 ) | 6065 ) |
5651 try: | 6066 try: |
5652 archiveFile = zipfile.ZipFile(archive, "w") | 6067 archiveFile = zipfile.ZipFile(archive, "w") |
5653 except OSError as why: | 6068 except OSError as why: |
5654 EricMessageBox.critical( | 6069 EricMessageBox.critical( |
5655 self.ui, | 6070 self.ui, |
5656 self.tr("Create Plugin Archive"), | 6071 self.tr("Create Plugin Archive"), |
5657 self.tr( | 6072 self.tr( |
5658 """<p>The eric plugin archive file <b>{0}</b>""" | 6073 """<p>The eric plugin archive file <b>{0}</b>""" |
5659 """ could not be created.</p>""" | 6074 """ could not be created.</p>""" |
5660 """<p>Reason: {1}</p>""").format(archive, str(why))) | 6075 """<p>Reason: {1}</p>""" |
6076 ).format(archive, str(why)), | |
6077 ) | |
5661 errors += 1 | 6078 errors += 1 |
5662 continue | 6079 continue |
5663 | 6080 |
5664 for name in names: | 6081 for name in names: |
5665 if name: | 6082 if name: |
5666 try: | 6083 try: |
5667 self.__createZipDirEntries( | 6084 self.__createZipDirEntries(os.path.split(name)[0], archiveFile) |
5668 os.path.split(name)[0], archiveFile) | |
5669 if snapshot and name == self.pdata["MAINSCRIPT"]: | 6085 if snapshot and name == self.pdata["MAINSCRIPT"]: |
5670 snapshotSource, version = ( | 6086 snapshotSource, version = self.__createSnapshotSource( |
5671 self.__createSnapshotSource( | 6087 os.path.join(self.ppath, self.pdata["MAINSCRIPT"]) |
5672 os.path.join(self.ppath, | |
5673 self.pdata["MAINSCRIPT"])) | |
5674 ) | 6088 ) |
5675 archiveFile.writestr(name, snapshotSource) | 6089 archiveFile.writestr(name, snapshotSource) |
5676 else: | 6090 else: |
5677 archiveFile.write(os.path.join(self.ppath, name), | 6091 archiveFile.write(os.path.join(self.ppath, name), name) |
5678 name) | |
5679 if name == self.pdata["MAINSCRIPT"]: | 6092 if name == self.pdata["MAINSCRIPT"]: |
5680 version = self.__pluginExtractVersion( | 6093 version = self.__pluginExtractVersion( |
5681 os.path.join(self.ppath, | 6094 os.path.join(self.ppath, self.pdata["MAINSCRIPT"]) |
5682 self.pdata["MAINSCRIPT"])) | 6095 ) |
5683 if archiveVersion and ( | 6096 if archiveVersion and ( |
5684 self.__pluginVersionToTuple(version) < | 6097 self.__pluginVersionToTuple(version) |
5685 self.__pluginVersionToTuple(archiveVersion) | 6098 < self.__pluginVersionToTuple(archiveVersion) |
5686 ): | 6099 ): |
5687 version = archiveVersion | 6100 version = archiveVersion |
5688 except OSError as why: | 6101 except OSError as why: |
5689 EricMessageBox.critical( | 6102 EricMessageBox.critical( |
5690 self.ui, | 6103 self.ui, |
5691 self.tr("Create Plugin Archive"), | 6104 self.tr("Create Plugin Archive"), |
5692 self.tr( | 6105 self.tr( |
5693 """<p>The file <b>{0}</b> could not be""" | 6106 """<p>The file <b>{0}</b> could not be""" |
5694 """ stored in the archive. Ignoring it.</p>""" | 6107 """ stored in the archive. Ignoring it.</p>""" |
5695 """<p>Reason: {1}</p>""") | 6108 """<p>Reason: {1}</p>""" |
5696 .format(os.path.join(self.ppath, name), str(why))) | 6109 ).format(os.path.join(self.ppath, name), str(why)), |
6110 ) | |
5697 archiveFile.writestr("VERSION", version.encode("utf-8")) | 6111 archiveFile.writestr("VERSION", version.encode("utf-8")) |
5698 archiveFile.close() | 6112 archiveFile.close() |
5699 | 6113 |
5700 if archive not in self.pdata["OTHERS"]: | 6114 if archive not in self.pdata["OTHERS"]: |
5701 self.appendFile(archive) | 6115 self.appendFile(archive) |
5702 | 6116 |
5703 progress.setValue(len(selectedLists)) | 6117 progress.setValue(len(selectedLists)) |
5704 | 6118 |
5705 if errors: | 6119 if errors: |
5706 self.ui.showNotification( | 6120 self.ui.showNotification( |
5707 UI.PixmapCache.getPixmap("pluginArchive48"), | 6121 UI.PixmapCache.getPixmap("pluginArchive48"), |
5708 self.tr("Create Plugin Archive"), | 6122 self.tr("Create Plugin Archive"), |
5709 self.tr("<p>The eric plugin archive files were " | 6123 self.tr( |
5710 "created with some errors.</p>"), | 6124 "<p>The eric plugin archive files were " |
6125 "created with some errors.</p>" | |
6126 ), | |
5711 kind=NotificationTypes.CRITICAL, | 6127 kind=NotificationTypes.CRITICAL, |
5712 timeout=0) | 6128 timeout=0, |
6129 ) | |
5713 else: | 6130 else: |
5714 self.ui.showNotification( | 6131 self.ui.showNotification( |
5715 UI.PixmapCache.getPixmap("pluginArchive48"), | 6132 UI.PixmapCache.getPixmap("pluginArchive48"), |
5716 self.tr("Create Plugin Archive"), | 6133 self.tr("Create Plugin Archive"), |
5717 self.tr("<p>The eric plugin archive files were " | 6134 self.tr( |
5718 "created successfully.</p>")) | 6135 "<p>The eric plugin archive files were " "created successfully.</p>" |
5719 | 6136 ), |
6137 ) | |
6138 | |
5720 def __pluginCreateSnapshotArchives(self): | 6139 def __pluginCreateSnapshotArchives(self): |
5721 """ | 6140 """ |
5722 Private slot to create eric plugin archive snapshot releases. | 6141 Private slot to create eric plugin archive snapshot releases. |
5723 """ | 6142 """ |
5724 self.__pluginCreateArchives(True) | 6143 self.__pluginCreateArchives(True) |
5725 | 6144 |
5726 def __createZipDirEntries(self, path, zipFile): | 6145 def __createZipDirEntries(self, path, zipFile): |
5727 """ | 6146 """ |
5728 Private method to create dir entries in the zip file. | 6147 Private method to create dir entries in the zip file. |
5729 | 6148 |
5730 @param path name of the directory entry to create (string) | 6149 @param path name of the directory entry to create (string) |
5731 @param zipFile open ZipFile object (zipfile.ZipFile) | 6150 @param zipFile open ZipFile object (zipfile.ZipFile) |
5732 """ | 6151 """ |
5733 if path in ("", "/", "\\"): | 6152 if path in ("", "/", "\\"): |
5734 return | 6153 return |
5735 | 6154 |
5736 if not path.endswith("/") and not path.endswith("\\"): | 6155 if not path.endswith("/") and not path.endswith("\\"): |
5737 path = "{0}/".format(path) | 6156 path = "{0}/".format(path) |
5738 | 6157 |
5739 if path not in zipFile.namelist(): | 6158 if path not in zipFile.namelist(): |
5740 self.__createZipDirEntries(os.path.split(path[:-1])[0], zipFile) | 6159 self.__createZipDirEntries(os.path.split(path[:-1])[0], zipFile) |
5741 zipFile.writestr(path, b"") | 6160 zipFile.writestr(path, b"") |
5742 | 6161 |
5743 def __createSnapshotSource(self, filename): | 6162 def __createSnapshotSource(self, filename): |
5744 """ | 6163 """ |
5745 Private method to create a snapshot plugin version. | 6164 Private method to create a snapshot plugin version. |
5746 | 6165 |
5747 The version entry in the plugin module is modified to signify | 6166 The version entry in the plugin module is modified to signify |
5748 a snapshot version. This method appends the string "-snapshot-" | 6167 a snapshot version. This method appends the string "-snapshot-" |
5749 and date indicator to the version string. | 6168 and date indicator to the version string. |
5750 | 6169 |
5751 @param filename name of the plugin file to modify (string) | 6170 @param filename name of the plugin file to modify (string) |
5752 @return modified source (bytes), snapshot version string (string) | 6171 @return modified source (bytes), snapshot version string (string) |
5753 """ | 6172 """ |
5754 try: | 6173 try: |
5755 sourcelines, encoding = Utilities.readEncodedFile(filename) | 6174 sourcelines, encoding = Utilities.readEncodedFile(filename) |
5756 sourcelines = sourcelines.splitlines(True) | 6175 sourcelines = sourcelines.splitlines(True) |
5757 except (OSError, UnicodeError) as why: | 6176 except (OSError, UnicodeError) as why: |
5758 EricMessageBox.critical( | 6177 EricMessageBox.critical( |
5759 self.ui, | 6178 self.ui, |
5760 self.tr("Create Plugin Archive"), | 6179 self.tr("Create Plugin Archive"), |
5761 self.tr("""<p>The plugin file <b>{0}</b> could """ | 6180 self.tr( |
5762 """not be read.</p>""" | 6181 """<p>The plugin file <b>{0}</b> could """ |
5763 """<p>Reason: {1}</p>""") | 6182 """not be read.</p>""" |
5764 .format(filename, str(why))) | 6183 """<p>Reason: {1}</p>""" |
6184 ).format(filename, str(why)), | |
6185 ) | |
5765 return b"", "" | 6186 return b"", "" |
5766 | 6187 |
5767 lineno = 0 | 6188 lineno = 0 |
5768 while lineno < len(sourcelines): | 6189 while lineno < len(sourcelines): |
5769 if sourcelines[lineno].startswith("version = "): | 6190 if sourcelines[lineno].startswith("version = "): |
5770 # found the line to modify | 6191 # found the line to modify |
5771 datestr = time.strftime("%Y%m%d") | 6192 datestr = time.strftime("%Y%m%d") |
5772 lineend = sourcelines[lineno].replace( | 6193 lineend = sourcelines[lineno].replace(sourcelines[lineno].rstrip(), "") |
5773 sourcelines[lineno].rstrip(), "") | |
5774 sversion = "{0}-snapshot-{1}".format( | 6194 sversion = "{0}-snapshot-{1}".format( |
5775 sourcelines[lineno].replace("version = ", "") | 6195 sourcelines[lineno].replace("version = ", "").strip()[1:-1], datestr |
5776 .strip()[1:-1], | 6196 ) |
5777 datestr) | |
5778 sourcelines[lineno] = '{0} + "-snapshot-{1}"{2}'.format( | 6197 sourcelines[lineno] = '{0} + "-snapshot-{1}"{2}'.format( |
5779 sourcelines[lineno].rstrip(), datestr, lineend) | 6198 sourcelines[lineno].rstrip(), datestr, lineend |
6199 ) | |
5780 break | 6200 break |
5781 | 6201 |
5782 lineno += 1 | 6202 lineno += 1 |
5783 | 6203 |
5784 source = Utilities.encode("".join(sourcelines), encoding)[0] | 6204 source = Utilities.encode("".join(sourcelines), encoding)[0] |
5785 return source, sversion | 6205 return source, sversion |
5786 | 6206 |
5787 def __pluginExtractVersion(self, filename): | 6207 def __pluginExtractVersion(self, filename): |
5788 """ | 6208 """ |
5789 Private method to extract the version number entry. | 6209 Private method to extract the version number entry. |
5790 | 6210 |
5791 @param filename name of the plugin file (string) | 6211 @param filename name of the plugin file (string) |
5792 @return version string (string) | 6212 @return version string (string) |
5793 """ | 6213 """ |
5794 version = "0.0.0" | 6214 version = "0.0.0" |
5795 try: | 6215 try: |
5799 EricMessageBox.critical( | 6219 EricMessageBox.critical( |
5800 self.ui, | 6220 self.ui, |
5801 self.tr("Create Plugin Archive"), | 6221 self.tr("Create Plugin Archive"), |
5802 self.tr( | 6222 self.tr( |
5803 """<p>The plugin file <b>{0}</b> could """ | 6223 """<p>The plugin file <b>{0}</b> could """ |
5804 """not be read.</p> <p>Reason: {1}</p>""") | 6224 """not be read.</p> <p>Reason: {1}</p>""" |
5805 .format(filename, str(why))) | 6225 ).format(filename, str(why)), |
6226 ) | |
5806 return "" | 6227 return "" |
5807 | 6228 |
5808 for sourceline in sourcelines: | 6229 for sourceline in sourcelines: |
5809 if sourceline.startswith("version = "): | 6230 if sourceline.startswith("version = "): |
5810 version = ( | 6231 version = ( |
5811 sourceline.replace("version = ", "").strip() | 6232 sourceline.replace("version = ", "") |
5812 .replace('"', "").replace("'", "") | 6233 .strip() |
6234 .replace('"', "") | |
6235 .replace("'", "") | |
5813 ) | 6236 ) |
5814 break | 6237 break |
5815 | 6238 |
5816 return version | 6239 return version |
5817 | 6240 |
5818 ######################################################################### | 6241 ######################################################################### |
5819 ## Below are methods implementing the 'make' support | 6242 ## Below are methods implementing the 'make' support |
5820 ######################################################################### | 6243 ######################################################################### |
5821 | 6244 |
5822 def __showContextMenuMake(self): | 6245 def __showContextMenuMake(self): |
5823 """ | 6246 """ |
5824 Private slot called before the make menu is shown. | 6247 Private slot called before the make menu is shown. |
5825 """ | 6248 """ |
5826 self.showMenu.emit("Make", self.makeMenu) | 6249 self.showMenu.emit("Make", self.makeMenu) |
5827 | 6250 |
5828 def hasDefaultMakeParameters(self): | 6251 def hasDefaultMakeParameters(self): |
5829 """ | 6252 """ |
5830 Public method to test, if the project contains the default make | 6253 Public method to test, if the project contains the default make |
5831 parameters. | 6254 parameters. |
5832 | 6255 |
5833 @return flag indicating default parameter set | 6256 @return flag indicating default parameter set |
5834 @rtype bool | 6257 @rtype bool |
5835 """ | 6258 """ |
5836 return self.pdata["MAKEPARAMS"] == { | 6259 return self.pdata["MAKEPARAMS"] == { |
5837 "MakeEnabled": False, | 6260 "MakeEnabled": False, |
5839 "MakeFile": "", | 6262 "MakeFile": "", |
5840 "MakeTarget": "", | 6263 "MakeTarget": "", |
5841 "MakeParameters": "", | 6264 "MakeParameters": "", |
5842 "MakeTestOnly": True, | 6265 "MakeTestOnly": True, |
5843 } | 6266 } |
5844 | 6267 |
5845 def isMakeEnabled(self): | 6268 def isMakeEnabled(self): |
5846 """ | 6269 """ |
5847 Public method to test, if make is enabled for the project. | 6270 Public method to test, if make is enabled for the project. |
5848 | 6271 |
5849 @return flag indicating enabled make support | 6272 @return flag indicating enabled make support |
5850 @rtype bool | 6273 @rtype bool |
5851 """ | 6274 """ |
5852 return self.pdata["MAKEPARAMS"]["MakeEnabled"] | 6275 return self.pdata["MAKEPARAMS"]["MakeEnabled"] |
5853 | 6276 |
5854 @pyqtSlot() | 6277 @pyqtSlot() |
5855 def executeMake(self): | 6278 def executeMake(self): |
5856 """ | 6279 """ |
5857 Public slot to execute a project specific make run (auto-run) | 6280 Public slot to execute a project specific make run (auto-run) |
5858 (execute or question). | 6281 (execute or question). |
5859 """ | 6282 """ |
5860 self.__executeMake( | 6283 self.__executeMake( |
5861 questionOnly=self.pdata["MAKEPARAMS"]["MakeTestOnly"], | 6284 questionOnly=self.pdata["MAKEPARAMS"]["MakeTestOnly"], interactive=False |
5862 interactive=False) | 6285 ) |
5863 | 6286 |
5864 @pyqtSlot() | 6287 @pyqtSlot() |
5865 def __executeMake(self, questionOnly=False, interactive=True): | 6288 def __executeMake(self, questionOnly=False, interactive=True): |
5866 """ | 6289 """ |
5867 Private method to execute a project specific make run. | 6290 Private method to execute a project specific make run. |
5868 | 6291 |
5869 @param questionOnly flag indicating to ask make for changes only | 6292 @param questionOnly flag indicating to ask make for changes only |
5870 @type bool | 6293 @type bool |
5871 @param interactive flag indicating an interactive invocation (i.e. | 6294 @param interactive flag indicating an interactive invocation (i.e. |
5872 through a menu action) | 6295 through a menu action) |
5873 @type bool | 6296 @type bool |
5874 """ | 6297 """ |
5875 if ( | 6298 if ( |
5876 not self.pdata["MAKEPARAMS"]["MakeEnabled"] or | 6299 not self.pdata["MAKEPARAMS"]["MakeEnabled"] |
5877 self.__makeProcess is not None | 6300 or self.__makeProcess is not None |
5878 ): | 6301 ): |
5879 return | 6302 return |
5880 | 6303 |
5881 prog = ( | 6304 prog = ( |
5882 self.pdata["MAKEPARAMS"]["MakeExecutable"] | 6305 self.pdata["MAKEPARAMS"]["MakeExecutable"] |
5883 if self.pdata["MAKEPARAMS"]["MakeExecutable"] else | 6306 if self.pdata["MAKEPARAMS"]["MakeExecutable"] |
5884 Project.DefaultMake | 6307 else Project.DefaultMake |
5885 ) | 6308 ) |
5886 | 6309 |
5887 args = [] | 6310 args = [] |
5888 if self.pdata["MAKEPARAMS"]["MakeParameters"]: | 6311 if self.pdata["MAKEPARAMS"]["MakeParameters"]: |
5889 args.extend(Utilities.parseOptionString( | 6312 args.extend( |
5890 self.pdata["MAKEPARAMS"]["MakeParameters"])) | 6313 Utilities.parseOptionString(self.pdata["MAKEPARAMS"]["MakeParameters"]) |
5891 | 6314 ) |
6315 | |
5892 if self.pdata["MAKEPARAMS"]["MakeFile"]: | 6316 if self.pdata["MAKEPARAMS"]["MakeFile"]: |
5893 args.append("--makefile={0}".format( | 6317 args.append("--makefile={0}".format(self.pdata["MAKEPARAMS"]["MakeFile"])) |
5894 self.pdata["MAKEPARAMS"]["MakeFile"])) | 6318 |
5895 | |
5896 if questionOnly: | 6319 if questionOnly: |
5897 args.append("--question") | 6320 args.append("--question") |
5898 | 6321 |
5899 if self.pdata["MAKEPARAMS"]["MakeTarget"]: | 6322 if self.pdata["MAKEPARAMS"]["MakeTarget"]: |
5900 args.append(self.pdata["MAKEPARAMS"]["MakeTarget"]) | 6323 args.append(self.pdata["MAKEPARAMS"]["MakeTarget"]) |
5901 | 6324 |
5902 self.__makeProcess = QProcess(self) | 6325 self.__makeProcess = QProcess(self) |
5903 self.__makeProcess.readyReadStandardOutput.connect( | 6326 self.__makeProcess.readyReadStandardOutput.connect(self.__makeReadStdOut) |
5904 self.__makeReadStdOut) | 6327 self.__makeProcess.readyReadStandardError.connect(self.__makeReadStdErr) |
5905 self.__makeProcess.readyReadStandardError.connect( | |
5906 self.__makeReadStdErr) | |
5907 self.__makeProcess.finished.connect( | 6328 self.__makeProcess.finished.connect( |
5908 lambda exitCode, exitStatus: self.__makeFinished( | 6329 lambda exitCode, exitStatus: self.__makeFinished( |
5909 exitCode, exitStatus, questionOnly, interactive)) | 6330 exitCode, exitStatus, questionOnly, interactive |
6331 ) | |
6332 ) | |
5910 self.__makeProcess.setWorkingDirectory(self.getProjectPath()) | 6333 self.__makeProcess.setWorkingDirectory(self.getProjectPath()) |
5911 self.__makeProcess.start(prog, args) | 6334 self.__makeProcess.start(prog, args) |
5912 | 6335 |
5913 if not self.__makeProcess.waitForStarted(): | 6336 if not self.__makeProcess.waitForStarted(): |
5914 EricMessageBox.critical( | 6337 EricMessageBox.critical( |
5915 self.ui, | 6338 self.ui, |
5916 self.tr("Execute Make"), | 6339 self.tr("Execute Make"), |
5917 self.tr("""The make process did not start.""")) | 6340 self.tr("""The make process did not start."""), |
5918 | 6341 ) |
6342 | |
5919 self.__cleanupMake() | 6343 self.__cleanupMake() |
5920 | 6344 |
5921 @pyqtSlot() | 6345 @pyqtSlot() |
5922 def __makeReadStdOut(self): | 6346 def __makeReadStdOut(self): |
5923 """ | 6347 """ |
5924 Private slot to process process output received via stdout. | 6348 Private slot to process process output received via stdout. |
5925 """ | 6349 """ |
5926 if self.__makeProcess is not None: | 6350 if self.__makeProcess is not None: |
5927 output = str(self.__makeProcess.readAllStandardOutput(), | 6351 output = str( |
5928 Preferences.getSystem("IOEncoding"), | 6352 self.__makeProcess.readAllStandardOutput(), |
5929 'replace') | 6353 Preferences.getSystem("IOEncoding"), |
6354 "replace", | |
6355 ) | |
5930 self.appendStdout.emit(output) | 6356 self.appendStdout.emit(output) |
5931 | 6357 |
5932 @pyqtSlot() | 6358 @pyqtSlot() |
5933 def __makeReadStdErr(self): | 6359 def __makeReadStdErr(self): |
5934 """ | 6360 """ |
5935 Private slot to process process output received via stderr. | 6361 Private slot to process process output received via stderr. |
5936 """ | 6362 """ |
5937 if self.__makeProcess is not None: | 6363 if self.__makeProcess is not None: |
5938 error = str(self.__makeProcess.readAllStandardError(), | 6364 error = str( |
5939 Preferences.getSystem("IOEncoding"), | 6365 self.__makeProcess.readAllStandardError(), |
5940 'replace') | 6366 Preferences.getSystem("IOEncoding"), |
6367 "replace", | |
6368 ) | |
5941 self.appendStderr.emit(error) | 6369 self.appendStderr.emit(error) |
5942 | 6370 |
5943 def __makeFinished(self, exitCode, exitStatus, questionOnly, | 6371 def __makeFinished(self, exitCode, exitStatus, questionOnly, interactive=True): |
5944 interactive=True): | |
5945 """ | 6372 """ |
5946 Private slot handling the make process finished signal. | 6373 Private slot handling the make process finished signal. |
5947 | 6374 |
5948 @param exitCode exit code of the make process | 6375 @param exitCode exit code of the make process |
5949 @type int | 6376 @type int |
5950 @param exitStatus exit status of the make process | 6377 @param exitStatus exit status of the make process |
5951 @type QProcess.ExitStatus | 6378 @type QProcess.ExitStatus |
5952 @param questionOnly flag indicating a test only run | 6379 @param questionOnly flag indicating a test only run |
5957 """ | 6384 """ |
5958 if exitStatus == QProcess.ExitStatus.CrashExit: | 6385 if exitStatus == QProcess.ExitStatus.CrashExit: |
5959 EricMessageBox.critical( | 6386 EricMessageBox.critical( |
5960 self.ui, | 6387 self.ui, |
5961 self.tr("Execute Make"), | 6388 self.tr("Execute Make"), |
5962 self.tr("""The make process crashed.""")) | 6389 self.tr("""The make process crashed."""), |
6390 ) | |
5963 else: | 6391 else: |
5964 if questionOnly and exitCode == 1: | 6392 if questionOnly and exitCode == 1: |
5965 # a rebuild is needed | 6393 # a rebuild is needed |
5966 title = self.tr("Test for Changes") | 6394 title = self.tr("Test for Changes") |
5967 | 6395 |
5968 if self.pdata["MAKEPARAMS"]["MakeTarget"]: | 6396 if self.pdata["MAKEPARAMS"]["MakeTarget"]: |
5969 message = self.tr( | 6397 message = self.tr( |
5970 """<p>There are changes that require the configured""" | 6398 """<p>There are changes that require the configured""" |
5971 """ make target <b>{0}</b> to be rebuilt.</p>""" | 6399 """ make target <b>{0}</b> to be rebuilt.</p>""" |
5972 ).format(self.pdata["MAKEPARAMS"]["MakeTarget"]) | 6400 ).format(self.pdata["MAKEPARAMS"]["MakeTarget"]) |
5973 else: | 6401 else: |
5974 message = self.tr( | 6402 message = self.tr( |
5975 """<p>There are changes that require the default""" | 6403 """<p>There are changes that require the default""" |
5976 """ make target to be rebuilt.</p>""") | 6404 """ make target to be rebuilt.</p>""" |
5977 | 6405 ) |
6406 | |
5978 self.ui.showNotification( | 6407 self.ui.showNotification( |
5979 UI.PixmapCache.getPixmap("makefile48"), | 6408 UI.PixmapCache.getPixmap("makefile48"), |
5980 title, | 6409 title, |
5981 message, | 6410 message, |
5982 kind=NotificationTypes.WARNING, | 6411 kind=NotificationTypes.WARNING, |
5983 timeout=0) | 6412 timeout=0, |
6413 ) | |
5984 elif exitCode > 1: | 6414 elif exitCode > 1: |
5985 EricMessageBox.critical( | 6415 EricMessageBox.critical( |
5986 self.ui, | 6416 self.ui, |
5987 self.tr("Execute Make"), | 6417 self.tr("Execute Make"), |
5988 self.tr("""The makefile contains errors.""")) | 6418 self.tr("""The makefile contains errors."""), |
5989 | 6419 ) |
6420 | |
5990 self.__cleanupMake() | 6421 self.__cleanupMake() |
5991 | 6422 |
5992 def __cleanupMake(self): | 6423 def __cleanupMake(self): |
5993 """ | 6424 """ |
5994 Private method to clean up make related stuff. | 6425 Private method to clean up make related stuff. |
5995 """ | 6426 """ |
5996 self.__makeProcess.readyReadStandardOutput.disconnect() | 6427 self.__makeProcess.readyReadStandardOutput.disconnect() |
5997 self.__makeProcess.readyReadStandardError.disconnect() | 6428 self.__makeProcess.readyReadStandardError.disconnect() |
5998 self.__makeProcess.finished.disconnect() | 6429 self.__makeProcess.finished.disconnect() |
5999 self.__makeProcess.deleteLater() | 6430 self.__makeProcess.deleteLater() |
6000 self.__makeProcess = None | 6431 self.__makeProcess = None |
6001 | 6432 |
6002 ######################################################################### | 6433 ######################################################################### |
6003 ## Below are methods implementing some 'IDL' support functions | 6434 ## Below are methods implementing some 'IDL' support functions |
6004 ######################################################################### | 6435 ######################################################################### |
6005 | 6436 |
6006 def hasDefaultIdlCompilerParameters(self): | 6437 def hasDefaultIdlCompilerParameters(self): |
6007 """ | 6438 """ |
6008 Public method to test, if the project contains the default IDL compiler | 6439 Public method to test, if the project contains the default IDL compiler |
6009 parameters. | 6440 parameters. |
6010 | 6441 |
6011 @return flag indicating default parameter set | 6442 @return flag indicating default parameter set |
6012 @rtype bool | 6443 @rtype bool |
6013 """ | 6444 """ |
6014 return self.pdata["IDLPARAMS"] == { | 6445 return self.pdata["IDLPARAMS"] == { |
6015 "IncludeDirs": [], | 6446 "IncludeDirs": [], |
6016 "DefinedNames": [], | 6447 "DefinedNames": [], |
6017 "UndefinedNames": [], | 6448 "UndefinedNames": [], |
6018 } | 6449 } |
6019 | 6450 |
6020 ######################################################################### | 6451 ######################################################################### |
6021 ## Below are methods implementing some 'UIC' support functions | 6452 ## Below are methods implementing some 'UIC' support functions |
6022 ######################################################################### | 6453 ######################################################################### |
6023 | 6454 |
6024 def hasDefaultUicCompilerParameters(self): | 6455 def hasDefaultUicCompilerParameters(self): |
6025 """ | 6456 """ |
6026 Public method to test, if the project contains the default uic compiler | 6457 Public method to test, if the project contains the default uic compiler |
6027 parameters. | 6458 parameters. |
6028 | 6459 |
6029 @return flag indicating default parameter set | 6460 @return flag indicating default parameter set |
6030 @rtype bool | 6461 @rtype bool |
6031 """ | 6462 """ |
6032 return self.pdata["UICPARAMS"] == { | 6463 return self.pdata["UICPARAMS"] == { |
6033 "Package": "", | 6464 "Package": "", |
6034 "RcSuffix": "", | 6465 "RcSuffix": "", |
6035 "PackagesRoot": "", | 6466 "PackagesRoot": "", |
6036 } | 6467 } |
6037 | 6468 |
6038 def getUicParameter(self, name): | 6469 def getUicParameter(self, name): |
6039 """ | 6470 """ |
6040 Public method to get a named uic related parameter. | 6471 Public method to get a named uic related parameter. |
6041 | 6472 |
6042 @param name name of the parameter | 6473 @param name name of the parameter |
6043 @type str | 6474 @type str |
6044 @return value of the given parameter | 6475 @return value of the given parameter |
6045 @rtype any, None in case on non-existence | 6476 @rtype any, None in case on non-existence |
6046 """ | 6477 """ |
6047 if name in self.pdata["UICPARAMS"]: | 6478 if name in self.pdata["UICPARAMS"]: |
6048 return self.pdata["UICPARAMS"][name] | 6479 return self.pdata["UICPARAMS"][name] |
6049 else: | 6480 else: |
6050 return None | 6481 return None |
6051 | 6482 |
6052 ######################################################################### | 6483 ######################################################################### |
6053 ## Below are methods implementing some 'RCC' support functions | 6484 ## Below are methods implementing some 'RCC' support functions |
6054 ######################################################################### | 6485 ######################################################################### |
6055 | 6486 |
6056 def hasDefaultRccCompilerParameters(self): | 6487 def hasDefaultRccCompilerParameters(self): |
6057 """ | 6488 """ |
6058 Public method to test, if the project contains the default rcc compiler | 6489 Public method to test, if the project contains the default rcc compiler |
6059 parameters. | 6490 parameters. |
6060 | 6491 |
6061 @return flag indicating default parameter set | 6492 @return flag indicating default parameter set |
6062 @rtype bool | 6493 @rtype bool |
6063 """ | 6494 """ |
6064 return ( | 6495 return self.pdata["RCCPARAMS"] == self.getDefaultRccCompilerParameters() |
6065 self.pdata["RCCPARAMS"] == self.getDefaultRccCompilerParameters() | 6496 |
6066 ) | |
6067 | |
6068 def getDefaultRccCompilerParameters(self): | 6497 def getDefaultRccCompilerParameters(self): |
6069 """ | 6498 """ |
6070 Public method to get the default rcc compiler parameters. | 6499 Public method to get the default rcc compiler parameters. |
6071 | 6500 |
6072 @return dictionary containing the default rcc compiler parameters | 6501 @return dictionary containing the default rcc compiler parameters |
6073 @rtype dict | 6502 @rtype dict |
6074 """ | 6503 """ |
6075 return { | 6504 return { |
6076 "CompressionThreshold": 70, # default value | 6505 "CompressionThreshold": 70, # default value |
6077 "CompressLevel": 0, # use zlib default | 6506 "CompressLevel": 0, # use zlib default |
6078 "CompressionDisable": False, | 6507 "CompressionDisable": False, |
6079 "PathPrefix": "", | 6508 "PathPrefix": "", |
6080 } | 6509 } |
6081 | 6510 |
6082 ######################################################################### | 6511 ######################################################################### |
6083 ## Below are methods implementing some 'docstring' support functions | 6512 ## Below are methods implementing some 'docstring' support functions |
6084 ######################################################################### | 6513 ######################################################################### |
6085 | 6514 |
6086 def hasDefaultDocstringParameter(self): | 6515 def hasDefaultDocstringParameter(self): |
6087 """ | 6516 """ |
6088 Public method to test, if the project contains the default docstring | 6517 Public method to test, if the project contains the default docstring |
6089 parameter. | 6518 parameter. |
6090 | 6519 |
6091 @return flag indicating default parameter | 6520 @return flag indicating default parameter |
6092 @rtype bool | 6521 @rtype bool |
6093 """ | 6522 """ |
6094 return self.pdata["DOCSTRING"] == "" | 6523 return self.pdata["DOCSTRING"] == "" |
6095 | 6524 |
6096 def getDocstringType(self): | 6525 def getDocstringType(self): |
6097 """ | 6526 """ |
6098 Public method to get the configured docstring style. | 6527 Public method to get the configured docstring style. |
6099 | 6528 |
6100 @return configured docstring style | 6529 @return configured docstring style |
6101 @rtype str | 6530 @rtype str |
6102 """ | 6531 """ |
6103 return self.pdata["DOCSTRING"] | 6532 return self.pdata["DOCSTRING"] |
6104 | 6533 |
6105 ######################################################################### | 6534 ######################################################################### |
6106 ## Below are methods implementing the 'SBOM' support | 6535 ## Below are methods implementing the 'SBOM' support |
6107 ######################################################################### | 6536 ######################################################################### |
6108 | 6537 |
6109 def __showContextMenuOthers(self): | 6538 def __showContextMenuOthers(self): |
6110 """ | 6539 """ |
6111 Private slot called before the 'Other Tools' menu is shown. | 6540 Private slot called before the 'Other Tools' menu is shown. |
6112 """ | 6541 """ |
6113 self.showMenu.emit("OtherTools", self.othersMenu) | 6542 self.showMenu.emit("OtherTools", self.othersMenu) |
6114 | 6543 |
6115 @pyqtSlot() | 6544 @pyqtSlot() |
6116 def __createSBOMFile(self): | 6545 def __createSBOMFile(self): |
6117 """ | 6546 """ |
6118 Private slot to create a SBOM file of the project dependencies. | 6547 Private slot to create a SBOM file of the project dependencies. |
6119 """ | 6548 """ |
6120 import CycloneDXInterface | 6549 import CycloneDXInterface |
6121 | 6550 |
6122 CycloneDXInterface.createCycloneDXFile("<project>") | 6551 CycloneDXInterface.createCycloneDXFile("<project>") |
6123 | 6552 |
6124 ######################################################################### | 6553 ######################################################################### |
6125 ## Below are methods implementing the 'Code Formatting' support | 6554 ## Below are methods implementing the 'Code Formatting' support |
6126 ######################################################################### | 6555 ######################################################################### |
6127 | 6556 |
6128 def __showContextMenuFormat(self): | 6557 def __showContextMenuFormat(self): |
6129 """ | 6558 """ |
6130 Private slot called before the 'Code Formatting' menu is shown. | 6559 Private slot called before the 'Code Formatting' menu is shown. |
6131 """ | 6560 """ |
6132 self.showMenu.emit("Formatting", self.othersMenu) | 6561 self.showMenu.emit("Formatting", self.othersMenu) |
6133 | 6562 |
6134 @pyqtSlot() | 6563 @pyqtSlot() |
6135 def __aboutBlack(self): | 6564 def __aboutBlack(self): |
6136 """ | 6565 """ |
6137 Private slot to show some information about the installed 'Black' tool. | 6566 Private slot to show some information about the installed 'Black' tool. |
6138 """ | 6567 """ |
6139 import black | 6568 import black |
6140 | 6569 |
6141 EricMessageBox.information( | 6570 EricMessageBox.information( |
6142 None, | 6571 None, |
6143 self.tr("About Black"), | 6572 self.tr("About Black"), |
6144 self.tr("""<p><b>Black Version {0}</b></p>""" | 6573 self.tr( |
6145 """<p><i>Black</i> is the uncompromising Python code""" | 6574 """<p><b>Black Version {0}</b></p>""" |
6146 """ formatter.</p>""").format(black.__version__) | 6575 """<p><i>Black</i> is the uncompromising Python code""" |
6147 ) | 6576 """ formatter.</p>""" |
6148 | 6577 ).format(black.__version__), |
6578 ) | |
6579 | |
6149 def __performFormatWithBlack(self, action): | 6580 def __performFormatWithBlack(self, action): |
6150 """ | 6581 """ |
6151 Private method to format the project sources using the 'Black' tool. | 6582 Private method to format the project sources using the 'Black' tool. |
6152 | 6583 |
6153 Following actions are supported. | 6584 Following actions are supported. |
6154 <ul> | 6585 <ul> |
6155 <li>BlackFormattingAction.Format - the code reformatting is performed</li> | 6586 <li>BlackFormattingAction.Format - the code reformatting is performed</li> |
6156 <li>BlackFormattingAction.Check - a check is performed, if code formatting | 6587 <li>BlackFormattingAction.Check - a check is performed, if code formatting |
6157 is necessary</li> | 6588 is necessary</li> |
6158 <li>BlackFormattingAction.Diff - a unified diff of potential code formatting | 6589 <li>BlackFormattingAction.Diff - a unified diff of potential code formatting |
6159 changes is generated</li> | 6590 changes is generated</li> |
6160 </ul> | 6591 </ul> |
6161 | 6592 |
6162 @param action formatting operation to be performed | 6593 @param action formatting operation to be performed |
6163 @type BlackFormattingAction | 6594 @type BlackFormattingAction |
6164 """ | 6595 """ |
6165 from CodeFormatting.BlackConfigurationDialog import BlackConfigurationDialog | 6596 from CodeFormatting.BlackConfigurationDialog import BlackConfigurationDialog |
6166 from CodeFormatting.BlackFormattingDialog import BlackFormattingDialog | 6597 from CodeFormatting.BlackFormattingDialog import BlackFormattingDialog |
6167 | 6598 |
6168 if ericApp().getObject("ViewManager").checkAllDirty(): | 6599 if ericApp().getObject("ViewManager").checkAllDirty(): |
6169 dlg = BlackConfigurationDialog(withProject=True) | 6600 dlg = BlackConfigurationDialog(withProject=True) |
6170 if dlg.exec() == QDialog.DialogCode.Accepted: | 6601 if dlg.exec() == QDialog.DialogCode.Accepted: |
6171 config = dlg.getConfiguration() | 6602 config = dlg.getConfiguration() |
6172 | 6603 |
6173 formattingDialog = BlackFormattingDialog( | 6604 formattingDialog = BlackFormattingDialog( |
6174 config, | 6605 config, |
6175 self.getProjectFiles("SOURCES", normalized=True), | 6606 self.getProjectFiles("SOURCES", normalized=True), |
6176 project=self, | 6607 project=self, |
6177 action=action | 6608 action=action, |
6178 ) | 6609 ) |
6179 formattingDialog.exec() | 6610 formattingDialog.exec() |
6180 | 6611 |
6612 | |
6181 # | 6613 # |
6182 # eflag: noqa = M601 | 6614 # eflag: noqa = M601 |