Project/ProjectSourcesBrowser.py

changeset 0
de9c2efb9d02
child 12
1d8dd9706f46
equal deleted inserted replaced
-1:000000000000 0:de9c2efb9d02
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2002 - 2009 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a class used to display the Sources part of the project.
8 """
9
10 import os
11 import sys
12
13 from PyQt4.QtCore import *
14 from PyQt4.QtGui import *
15
16 from E4Gui.E4Application import e4App
17
18 from UI.BrowserModel import BrowserFileItem, BrowserClassItem, BrowserMethodItem, \
19 BrowserClassAttributeItem
20 from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog
21 import UI.PixmapCache
22
23 from DataViews.CodeMetricsDialog import CodeMetricsDialog
24 from DataViews.PyCoverageDialog import PyCoverageDialog
25 from DataViews.PyProfileDialog import PyProfileDialog
26
27 from Graphics.UMLClassDiagram import UMLClassDiagram
28 from Graphics.ImportsDiagram import ImportsDiagram
29 from Graphics.ApplicationDiagram import ApplicationDiagram
30 from Graphics.PackageDiagram import PackageDiagram
31
32 from ProjectBrowserModel import ProjectBrowserFileItem, \
33 ProjectBrowserSimpleDirectoryItem, ProjectBrowserDirectoryItem, \
34 ProjectBrowserSourceType
35 from ProjectBaseBrowser import ProjectBaseBrowser
36 from NewPythonPackageDialog import NewPythonPackageDialog
37
38 import Utilities
39
40 class ProjectSourcesBrowser(ProjectBaseBrowser):
41 """
42 A class used to display the Sources part of the project.
43
44 @signal closeSourceWindow(string) emitted after a file has been removed/deleted
45 from the project
46 @signal showMenu(string, QMenu) emitted when a menu is about to be shown. The name
47 of the menu and a reference to the menu are given.
48 """
49 def __init__(self, project, parent = None):
50 """
51 Constructor
52
53 @param project reference to the project object
54 @param parent parent widget of this browser (QWidget)
55 """
56 ProjectBaseBrowser.__init__(self, project, ProjectBrowserSourceType, parent)
57
58 self.selectedItemsFilter = \
59 [ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem]
60
61 self.setWindowTitle(self.trUtf8('Sources'))
62
63 self.setWhatsThis(self.trUtf8(
64 """<b>Project Sources Browser</b>"""
65 """<p>This allows to easily see all sources contained in the current"""
66 """ project. Several actions can be executed via the context menu.</p>"""
67 ))
68
69 self.connect(project, SIGNAL("prepareRepopulateItem"),
70 self._prepareRepopulateItem)
71 self.connect(project, SIGNAL("completeRepopulateItem"),
72 self._completeRepopulateItem)
73
74 self.codemetrics = None
75 self.codecoverage = None
76 self.profiledata = None
77 self.classDiagram = None
78 self.importsDiagram = None
79 self.packageDiagram = None
80 self.applicationDiagram = None
81
82 def __closeAllWindows(self):
83 """
84 Private method to close all project related windows.
85 """
86 self.codemetrics and self.codemetrics.close()
87 self.codecoverage and self.codecoverage.close()
88 self.profiledata and self.profiledata.close()
89 self.classDiagram and self.classDiagram.close()
90 self.importsDiagram and self.importsDiagram.close()
91 self.packageDiagram and self.packageDiagram.close()
92 self.applicationDiagram and self.applicationDiagram.close()
93
94 def _projectClosed(self):
95 """
96 Protected slot to handle the projectClosed signal.
97 """
98 self.__closeAllWindows()
99 ProjectBaseBrowser._projectClosed(self)
100
101 def _createPopupMenus(self):
102 """
103 Protected overloaded method to generate the popup menu.
104 """
105 ProjectBaseBrowser._createPopupMenus(self)
106 self.sourceMenuActions = {}
107
108 if self.project.pdata["PROGLANGUAGE"][0] in ["Python", "Python3"]:
109 self.__createPythonPopupMenus()
110 elif self.project.pdata["PROGLANGUAGE"][0] == "Ruby":
111 self.__createRubyPopupMenus()
112
113 def __createPythonPopupMenus(self):
114 """
115 Privat method to generate the popup menus for a Python project.
116 """
117 self.checksMenu = QMenu(self.trUtf8('Check'))
118 self.connect(self.checksMenu, SIGNAL('aboutToShow()'),
119 self.__showContextMenuCheck)
120
121 self.showMenu = QMenu(self.trUtf8('Show'))
122 self.showMenu.addAction(self.trUtf8('Code metrics...'), self.__showCodeMetrics)
123 self.coverageMenuAction = self.showMenu.addAction(\
124 self.trUtf8('Code coverage...'), self.__showCodeCoverage)
125 self.profileMenuAction = self.showMenu.addAction(\
126 self.trUtf8('Profile data...'), self.__showProfileData)
127 self.connect(self.showMenu, SIGNAL('aboutToShow()'), self.__showContextMenuShow)
128
129 self.graphicsMenu = QMenu(self.trUtf8('Diagrams'))
130 self.classDiagramAction = self.graphicsMenu.addAction(\
131 self.trUtf8("Class Diagram..."), self.__showClassDiagram)
132 self.graphicsMenu.addAction(\
133 self.trUtf8("Package Diagram..."), self.__showPackageDiagram)
134 self.importsDiagramAction = self.graphicsMenu.addAction(\
135 self.trUtf8("Imports Diagram..."), self.__showImportsDiagram)
136 self.graphicsMenu.addAction(\
137 self.trUtf8("Application Diagram..."), self.__showApplicationDiagram)
138 self.connect(self.graphicsMenu, SIGNAL('aboutToShow()'),
139 self.__showContextMenuGraphics)
140
141 self.unittestAction = self.sourceMenu.addAction(\
142 self.trUtf8('Run unittest...'), self.handleUnittest)
143 self.sourceMenu.addSeparator()
144 act = self.sourceMenu.addAction(self.trUtf8('Rename file'), self._renameFile)
145 self.menuActions.append(act)
146 act = self.sourceMenu.addAction(self.trUtf8('Remove from project'),
147 self._removeFile)
148 self.menuActions.append(act)
149 act = self.sourceMenu.addAction(self.trUtf8('Delete'), self.__deleteFile)
150 self.menuActions.append(act)
151 self.sourceMenu.addSeparator()
152 self.sourceMenu.addAction(self.trUtf8('New package...'),
153 self.__addNewPackage)
154 self.sourceMenu.addAction(self.trUtf8('Add source files...'),
155 self.__addSourceFiles)
156 self.sourceMenu.addAction(self.trUtf8('Add source directory...'),
157 self.__addSourceDirectory)
158 self.sourceMenu.addSeparator()
159 act = self.sourceMenu.addMenu(self.graphicsMenu)
160 self.sourceMenu.addSeparator()
161 self.sourceMenu.addMenu(self.checksMenu)
162 self.sourceMenu.addSeparator()
163 self.sourceMenuActions["Show"] = \
164 self.sourceMenu.addMenu(self.showMenu)
165 self.sourceMenu.addSeparator()
166 self.sourceMenu.addAction(self.trUtf8('Copy Path to Clipboard'),
167 self._copyToClipboard)
168 self.sourceMenu.addSeparator()
169 self.sourceMenu.addAction(self.trUtf8('Expand all directories'),
170 self._expandAllDirs)
171 self.sourceMenu.addAction(self.trUtf8('Collapse all directories'),
172 self._collapseAllDirs)
173 self.sourceMenu.addSeparator()
174 self.sourceMenu.addAction(self.trUtf8('Configure...'), self._configure)
175
176 self.menu.addSeparator()
177 self.menu.addAction(self.trUtf8('New package...'),
178 self.__addNewPackage)
179 self.menu.addAction(self.trUtf8('Add source files...'),
180 self.__addSourceFiles)
181 self.menu.addAction(self.trUtf8('Add source directory...'),
182 self.__addSourceDirectory)
183 self.menu.addSeparator()
184 self.menu.addAction(self.trUtf8('Expand all directories'),
185 self._expandAllDirs)
186 self.menu.addAction(self.trUtf8('Collapse all directories'),
187 self._collapseAllDirs)
188 self.menu.addSeparator()
189 self.menu.addAction(self.trUtf8('Configure...'), self._configure)
190
191 self.backMenu = QMenu(self)
192 self.backMenu.addAction(self.trUtf8('New package...'),
193 self.__addNewPackage)
194 self.backMenu.addAction(self.trUtf8('Add source files...'),
195 self.project.addSourceFiles)
196 self.backMenu.addAction(self.trUtf8('Add source directory...'),
197 self.project.addSourceDir)
198 self.backMenu.addSeparator()
199 self.backMenu.addAction(self.trUtf8('Expand all directories'),
200 self._expandAllDirs)
201 self.backMenu.addAction(self.trUtf8('Collapse all directories'),
202 self._collapseAllDirs)
203 self.backMenu.addSeparator()
204 self.backMenu.addAction(self.trUtf8('Configure...'), self._configure)
205 self.backMenu.setEnabled(False)
206
207 self.multiMenu.addSeparator()
208 act = self.multiMenu.addAction(self.trUtf8('Remove from project'),
209 self._removeFile)
210 self.multiMenuActions.append(act)
211 act = self.multiMenu.addAction(self.trUtf8('Delete'), self.__deleteFile)
212 self.multiMenuActions.append(act)
213 self.multiMenu.addSeparator()
214 self.multiMenu.addAction(self.trUtf8('Expand all directories'),
215 self._expandAllDirs)
216 self.multiMenu.addAction(self.trUtf8('Collapse all directories'),
217 self._collapseAllDirs)
218 self.multiMenu.addSeparator()
219 self.multiMenu.addAction(self.trUtf8('Configure...'), self._configure)
220
221 self.dirMenu = QMenu(self)
222 act = self.dirMenu.addAction(self.trUtf8('Remove from project'), self._removeDir)
223 self.dirMenuActions.append(act)
224 self.dirMenu.addSeparator()
225 self.dirMenu.addAction(self.trUtf8('New package...'), self.__addNewPackage)
226 self.dirMenu.addAction(self.trUtf8('Add source files...'), self.__addSourceFiles)
227 self.dirMenu.addAction(self.trUtf8('Add source directory...'),
228 self.__addSourceDirectory)
229 self.dirMenu.addSeparator()
230 act = self.dirMenu.addMenu(self.graphicsMenu)
231 self.dirMenu.addSeparator()
232 self.dirMenu.addMenu(self.checksMenu)
233 self.dirMenu.addSeparator()
234 self.dirMenu.addAction(self.trUtf8('Copy Path to Clipboard'),
235 self._copyToClipboard)
236 self.dirMenu.addSeparator()
237 self.dirMenu.addAction(self.trUtf8('Expand all directories'),
238 self._expandAllDirs)
239 self.dirMenu.addAction(self.trUtf8('Collapse all directories'),
240 self._collapseAllDirs)
241 self.dirMenu.addSeparator()
242 self.dirMenu.addAction(self.trUtf8('Configure...'), self._configure)
243
244 self.dirMultiMenu = QMenu(self)
245 self.dirMultiMenu.addAction(self.trUtf8('Expand all directories'),
246 self._expandAllDirs)
247 self.dirMultiMenu.addAction(self.trUtf8('Collapse all directories'),
248 self._collapseAllDirs)
249 self.dirMultiMenu.addSeparator()
250 self.dirMultiMenu.addAction(self.trUtf8('Configure...'), self._configure)
251
252 self.connect(self.sourceMenu, SIGNAL('aboutToShow()'),
253 self.__showContextMenu)
254 self.connect(self.multiMenu, SIGNAL('aboutToShow()'),
255 self.__showContextMenuMulti)
256 self.connect(self.dirMenu, SIGNAL('aboutToShow()'),
257 self.__showContextMenuDir)
258 self.connect(self.dirMultiMenu, SIGNAL('aboutToShow()'),
259 self.__showContextMenuDirMulti)
260 self.connect(self.backMenu, SIGNAL('aboutToShow()'),
261 self.__showContextMenuBack)
262 self.mainMenu = self.sourceMenu
263
264 def __createRubyPopupMenus(self):
265 """
266 Privat method to generate the popup menus for a Ruby project.
267 """
268 self.graphicsMenu = QMenu(self.trUtf8('Diagrams'))
269 self.classDiagramAction = self.graphicsMenu.addAction(\
270 self.trUtf8("Class Diagram..."), self.__showClassDiagram)
271 self.graphicsMenu.addAction(self.trUtf8("Package Diagram..."),
272 self.__showPackageDiagram)
273 self.graphicsMenu.addAction(self.trUtf8("Application Diagram..."),
274 self.__showApplicationDiagram)
275
276 self.sourceMenu.addSeparator()
277 act = self.sourceMenu.addAction(self.trUtf8('Rename file'), self._renameFile)
278 self.menuActions.append(act)
279 act = self.sourceMenu.addAction(self.trUtf8('Remove from project'),
280 self._removeFile)
281 self.menuActions.append(act)
282 act = self.sourceMenu.addAction(self.trUtf8('Delete'), self.__deleteFile)
283 self.menuActions.append(act)
284 self.sourceMenu.addSeparator()
285 self.sourceMenu.addAction(self.trUtf8('Add source files...'),
286 self.__addSourceFiles)
287 self.sourceMenu.addAction(self.trUtf8('Add source directory...'),
288 self.__addSourceDirectory)
289 self.sourceMenu.addSeparator()
290 act = self.sourceMenu.addMenu(self.graphicsMenu)
291 self.sourceMenu.addSeparator()
292 self.sourceMenu.addAction(self.trUtf8('Expand all directories'),
293 self._expandAllDirs)
294 self.sourceMenu.addAction(self.trUtf8('Collapse all directories'),
295 self._collapseAllDirs)
296 self.sourceMenu.addSeparator()
297 self.sourceMenu.addAction(self.trUtf8('Configure...'), self._configure)
298
299 self.menu.addSeparator()
300 self.menu.addAction(self.trUtf8('Add source files...'), self.__addSourceFiles)
301 self.menu.addAction(self.trUtf8('Add source directory...'),
302 self.__addSourceDirectory)
303 self.menu.addSeparator()
304 self.menu.addAction(self.trUtf8('Expand all directories'),
305 self._expandAllDirs)
306 self.menu.addAction(self.trUtf8('Collapse all directories'),
307 self._collapseAllDirs)
308 self.menu.addSeparator()
309 self.menu.addAction(self.trUtf8('Configure...'), self._configure)
310
311 self.backMenu = QMenu(self)
312 self.backMenu.addAction(self.trUtf8('Add source files...'),
313 self.project.addSourceFiles)
314 self.backMenu.addAction(self.trUtf8('Add source directory...'),
315 self.project.addSourceDir)
316 self.backMenu.addSeparator()
317 self.backMenu.addAction(self.trUtf8('Expand all directories'),
318 self._expandAllDirs)
319 self.backMenu.addAction(self.trUtf8('Collapse all directories'),
320 self._collapseAllDirs)
321 self.backMenu.setEnabled(False)
322 self.backMenu.addSeparator()
323 self.backMenu.addAction(self.trUtf8('Configure...'), self._configure)
324
325 self.multiMenu.addSeparator()
326 act = self.multiMenu.addAction(self.trUtf8('Remove from project'),
327 self._removeFile)
328 self.multiMenuActions.append(act)
329 act = self.multiMenu.addAction(self.trUtf8('Delete'), self.__deleteFile)
330 self.multiMenuActions.append(act)
331 self.multiMenu.addSeparator()
332 self.multiMenu.addAction(self.trUtf8('Expand all directories'),
333 self._expandAllDirs)
334 self.multiMenu.addAction(self.trUtf8('Collapse all directories'),
335 self._collapseAllDirs)
336 self.multiMenu.addSeparator()
337 self.multiMenu.addAction(self.trUtf8('Configure...'), self._configure)
338
339 self.dirMenu = QMenu(self)
340 act = self.dirMenu.addAction(self.trUtf8('Remove from project'), self._removeDir)
341 self.dirMenuActions.append(act)
342 self.dirMenu.addSeparator()
343 self.dirMenu.addAction(self.trUtf8('Add source files...'), self.__addSourceFiles)
344 self.dirMenu.addAction(self.trUtf8('Add source directory...'),
345 self.__addSourceDirectory)
346 self.dirMenu.addSeparator()
347 act = self.dirMenu.addMenu(self.graphicsMenu)
348 self.dirMenu.addSeparator()
349 self.dirMenu.addAction(self.trUtf8('Expand all directories'),
350 self._expandAllDirs)
351 self.dirMenu.addAction(self.trUtf8('Collapse all directories'),
352 self._collapseAllDirs)
353 self.dirMenu.addSeparator()
354 self.dirMenu.addAction(self.trUtf8('Configure...'), self._configure)
355
356 self.dirMultiMenu = QMenu(self)
357 self.dirMultiMenu.addAction(self.trUtf8('Expand all directories'),
358 self._expandAllDirs)
359 self.dirMultiMenu.addAction(self.trUtf8('Collapse all directories'),
360 self._collapseAllDirs)
361 self.dirMultiMenu.addSeparator()
362 self.dirMultiMenu.addAction(self.trUtf8('Configure...'), self._configure)
363
364 self.connect(self.sourceMenu, SIGNAL('aboutToShow()'),
365 self.__showContextMenu)
366 self.connect(self.multiMenu, SIGNAL('aboutToShow()'),
367 self.__showContextMenuMulti)
368 self.connect(self.dirMenu, SIGNAL('aboutToShow()'),
369 self.__showContextMenuDir)
370 self.connect(self.dirMultiMenu, SIGNAL('aboutToShow()'),
371 self.__showContextMenuDirMulti)
372 self.connect(self.backMenu, SIGNAL('aboutToShow()'),
373 self.__showContextMenuBack)
374 self.mainMenu = self.sourceMenu
375
376 def _contextMenuRequested(self, coord):
377 """
378 Protected slot to show the context menu.
379
380 @param coord the position of the mouse pointer (QPoint)
381 """
382 if not self.project.isOpen():
383 return
384
385 try:
386 categories = self.getSelectedItemsCountCategorized(\
387 [ProjectBrowserFileItem, BrowserClassItem,
388 BrowserMethodItem, ProjectBrowserSimpleDirectoryItem])
389 cnt = categories["sum"]
390 if cnt <= 1:
391 index = self.indexAt(coord)
392 if index.isValid():
393 self._selectSingleItem(index)
394 categories = self.getSelectedItemsCountCategorized(\
395 [ProjectBrowserFileItem, BrowserClassItem,
396 BrowserMethodItem, ProjectBrowserSimpleDirectoryItem])
397 cnt = categories["sum"]
398
399 bfcnt = categories[unicode(ProjectBrowserFileItem)]
400 cmcnt = categories[unicode(BrowserClassItem)] + \
401 categories[unicode(BrowserMethodItem)]
402 sdcnt = categories[unicode(ProjectBrowserSimpleDirectoryItem)]
403 if cnt > 1 and cnt == bfcnt:
404 self.multiMenu.popup(self.mapToGlobal(coord))
405 elif cnt > 1 and cnt == sdcnt:
406 self.dirMultiMenu.popup(self.mapToGlobal(coord))
407 else:
408 index = self.indexAt(coord)
409 if cnt == 1 and index.isValid():
410 if bfcnt == 1 or cmcnt == 1:
411 itm = self.model().item(index)
412 if isinstance(itm, ProjectBrowserFileItem):
413 fn = itm.fileName()
414 if self.project.pdata["PROGLANGUAGE"][0] in \
415 ["Python", "Python3"]:
416 if fn.endswith('.ptl'):
417 for act in self.sourceMenuActions.values():
418 act.setEnabled(False)
419 self.classDiagramAction.setEnabled(True)
420 self.importsDiagramAction.setEnabled(True)
421 self.unittestAction.setEnabled(False)
422 self.checksMenu.menuAction().setEnabled(False)
423 elif fn.endswith('.rb'): # entry for mixed mode programs
424 for act in self.sourceMenuActions.values():
425 act.setEnabled(False)
426 self.classDiagramAction.setEnabled(True)
427 self.importsDiagramAction.setEnabled(False)
428 self.unittestAction.setEnabled(False)
429 self.checksMenu.menuAction().setEnabled(False)
430 else: # assume the source file is a Python file
431 for act in self.sourceMenuActions.values():
432 act.setEnabled(True)
433 self.classDiagramAction.setEnabled(True)
434 self.importsDiagramAction.setEnabled(True)
435 self.unittestAction.setEnabled(True)
436 self.checksMenu.menuAction().setEnabled(True)
437 self.sourceMenu.popup(self.mapToGlobal(coord))
438 elif isinstance(itm, BrowserClassItem) or \
439 isinstance(itm, BrowserMethodItem):
440 self.menu.popup(self.mapToGlobal(coord))
441 else:
442 self.backMenu.popup(self.mapToGlobal(coord))
443 elif sdcnt == 1:
444 self.classDiagramAction.setEnabled(False)
445 self.dirMenu.popup(self.mapToGlobal(coord))
446 else:
447 self.backMenu.popup(self.mapToGlobal(coord))
448 else:
449 self.backMenu.popup(self.mapToGlobal(coord))
450 except:
451 pass
452
453 def __showContextMenu(self):
454 """
455 Private slot called by the sourceMenu aboutToShow signal.
456 """
457 ProjectBaseBrowser._showContextMenu(self, self.sourceMenu)
458
459 self.emit(SIGNAL("showMenu"), "Main", self.sourceMenu)
460
461 def __showContextMenuMulti(self):
462 """
463 Private slot called by the multiMenu aboutToShow signal.
464 """
465 ProjectBaseBrowser._showContextMenuMulti(self, self.multiMenu)
466
467 self.emit(SIGNAL("showMenu"), "MainMulti", self.multiMenu)
468
469 def __showContextMenuDir(self):
470 """
471 Private slot called by the dirMenu aboutToShow signal.
472 """
473 ProjectBaseBrowser._showContextMenuDir(self, self.dirMenu)
474
475 self.emit(SIGNAL("showMenu"), "MainDir", self.dirMenu)
476
477 def __showContextMenuDirMulti(self):
478 """
479 Private slot called by the dirMultiMenu aboutToShow signal.
480 """
481 ProjectBaseBrowser._showContextMenuDirMulti(self, self.dirMultiMenu)
482
483 self.emit(SIGNAL("showMenu"), "MainDirMulti", self.dirMultiMenu)
484
485 def __showContextMenuBack(self):
486 """
487 Private slot called by the backMenu aboutToShow signal.
488 """
489 ProjectBaseBrowser._showContextMenuBack(self, self.backMenu)
490
491 self.emit(SIGNAL("showMenu"), "MainBack", self.backMenu)
492
493 def __showContextMenuShow(self):
494 """
495 Private slot called before the show menu is shown.
496 """
497 prEnable = False
498 coEnable = False
499
500 # first check if the file belongs to a project and there is
501 # a project coverage file
502 fn = self.project.getMainScript(True)
503 if fn is not None:
504 tfn = Utilities.getTestFileName(fn)
505 basename = os.path.splitext(fn)[0]
506 tbasename = os.path.splitext(tfn)[0]
507 prEnable = prEnable or \
508 os.path.isfile("%s.profile" % basename) or \
509 os.path.isfile("%s.profile" % tbasename)
510 coEnable = coEnable or \
511 os.path.isfile("%s.coverage" % basename) or \
512 os.path.isfile("%s.coverage" % tbasename)
513
514 # now check the selected item
515 itm = self.model().item(self.currentIndex())
516 fn = itm.fileName()
517 if fn is not None:
518 basename = os.path.splitext(fn)[0]
519 prEnable = prEnable or \
520 os.path.isfile("%s.profile" % basename)
521 coEnable = coEnable or \
522 os.path.isfile("%s.coverage" % basename)
523
524 self.profileMenuAction.setEnabled(prEnable)
525 self.coverageMenuAction.setEnabled(coEnable)
526
527 self.emit(SIGNAL("showMenu"), "Show", self.showMenu)
528
529 def _openItem(self):
530 """
531 Protected slot to handle the open popup menu entry.
532 """
533 itmList = self.getSelectedItems(\
534 [BrowserFileItem, BrowserClassItem, BrowserMethodItem,
535 BrowserClassAttributeItem])
536
537 for itm in itmList:
538 if isinstance(itm, BrowserFileItem):
539 if itm.isPythonFile():
540 self.emit(SIGNAL('sourceFile'), itm.fileName(), 1, "Python")
541 elif itm.isRubyFile():
542 self.emit(SIGNAL('sourceFile'), itm.fileName(), 1, "Ruby")
543 elif itm.isDFile():
544 self.emit(SIGNAL('sourceFile'), itm.fileName(), 1, "D")
545 else:
546 self.emit(SIGNAL('sourceFile'), itm.fileName())
547 elif isinstance(itm, BrowserClassItem):
548 self.emit(SIGNAL('sourceFile'), itm.fileName(),
549 itm.classObject().lineno)
550 elif isinstance(itm,BrowserMethodItem):
551 self.emit(SIGNAL('sourceFile'), itm.fileName(),
552 itm.functionObject().lineno)
553 elif isinstance(itm, BrowserClassAttributeItem):
554 self.emit(SIGNAL('sourceFile'), itm.fileName(),
555 itm.attributeObject().lineno)
556
557 def __addNewPackage(self):
558 """
559 Private method to add a new package to the project.
560 """
561 itm = self.model().item(self.currentIndex())
562 if isinstance(itm, ProjectBrowserFileItem) or \
563 isinstance(itm, BrowserClassItem) or \
564 isinstance(itm, BrowserMethodItem):
565 dn = os.path.dirname(itm.fileName())
566 elif isinstance(itm, ProjectBrowserSimpleDirectoryItem) or \
567 isinstance(itm, ProjectBrowserDirectoryItem):
568 dn = itm.dirName()
569 else:
570 dn = ""
571
572 dn = dn.replace(self.project.ppath, "")
573 if dn.startswith(os.sep):
574 dn = dn[1:]
575 dlg = NewPythonPackageDialog(dn, self)
576 if dlg.exec_() == QDialog.Accepted:
577 packageName = dlg.getData()
578 nameParts = packageName.split(".")
579 packagePath = self.project.ppath
580 packageFile = ""
581 for name in nameParts:
582 packagePath = os.path.join(packagePath, name)
583 if not os.path.exists(packagePath):
584 try:
585 os.mkdir(packagePath)
586 except IOError, err:
587 QMessageBox.critical(None,
588 self.trUtf8("Add new Python package"),
589 self.trUtf8("""<p>The package directory <b>{0}</b> could"""
590 """ not be created. Aborting...</p>"""
591 """<p>Reason: {1}</p>""")\
592 .format(packagePath, unicode(err)),
593 QMessageBox.StandardButtons(\
594 QMessageBox.Ok))
595 return
596 packageFile = os.path.join(packagePath, "__init__.py")
597 if not os.path.exists(packageFile):
598 try:
599 f = open(packageFile, "wb")
600 f.close()
601 except IOError, err:
602 QMessageBox.critical(None,
603 self.trUtf8("Add new Python package"),
604 self.trUtf8("""<p>The package file <b>{0}</b> could"""
605 """ not be created. Aborting...</p>"""
606 """<p>Reason: {1}</p>""")\
607 .format(packageFile, unicode(err)),
608 QMessageBox.StandardButtons(\
609 QMessageBox.Ok))
610 return
611 self.project.appendFile(packageFile)
612 if packageFile:
613 self.emit(SIGNAL('sourceFile'), packageFile)
614
615 def __addSourceFiles(self):
616 """
617 Private method to add a source file to the project.
618 """
619 itm = self.model().item(self.currentIndex())
620 if isinstance(itm, ProjectBrowserFileItem) or \
621 isinstance(itm, BrowserClassItem) or \
622 isinstance(itm, BrowserMethodItem):
623 dn = os.path.dirname(itm.fileName())
624 elif isinstance(itm, ProjectBrowserSimpleDirectoryItem) or \
625 isinstance(itm, ProjectBrowserDirectoryItem):
626 dn = itm.dirName()
627 else:
628 dn = None
629 self.project.addFiles('source', dn)
630
631 def __addSourceDirectory(self):
632 """
633 Private method to add source files of a directory to the project.
634 """
635 itm = self.model().item(self.currentIndex())
636 if isinstance(itm, ProjectBrowserFileItem) or \
637 isinstance(itm, BrowserClassItem) or \
638 isinstance(itm, BrowserMethodItem):
639 dn = os.path.dirname(itm.fileName())
640 elif isinstance(itm, ProjectBrowserSimpleDirectoryItem) or \
641 isinstance(itm, ProjectBrowserDirectoryItem):
642 dn = itm.dirName()
643 else:
644 dn = None
645 self.project.addDirectory('source', dn)
646
647 def __deleteFile(self):
648 """
649 Private method to delete files from the project.
650 """
651 itmList = self.getSelectedItems()
652
653 files = []
654 fullNames = []
655 for itm in itmList:
656 fn2 = itm.fileName()
657 fullNames.append(fn2)
658 fn = fn2.replace(self.project.ppath+os.sep, '')
659 files.append(fn)
660
661 dlg = DeleteFilesConfirmationDialog(self.parent(),
662 self.trUtf8("Delete files"),
663 self.trUtf8("Do you really want to delete these files from the project?"),
664 files)
665
666 if dlg.exec_() == QDialog.Accepted:
667 for fn2, fn in zip(fullNames, files):
668 self.emit(SIGNAL('closeSourceWindow'), fn2)
669 self.project.deleteFile(fn)
670
671 ############################################################################
672 ## Methods for the Checks submenu
673 ############################################################################
674
675 def __showContextMenuCheck(self):
676 """
677 Private slot called before the checks menu is shown.
678 """
679 self.emit(SIGNAL("showMenu"), "Checks", self.checksMenu)
680
681 ############################################################################
682 ## Methods for the Show submenu
683 ############################################################################
684
685 def __showCodeMetrics(self):
686 """
687 Private method to handle the code metrics context menu action.
688 """
689 itm = self.model().item(self.currentIndex())
690 fn = itm.fileName()
691
692 self.codemetrics = CodeMetricsDialog()
693 self.codemetrics.show()
694 self.codemetrics.start(fn)
695
696 def __showCodeCoverage(self):
697 """
698 Private method to handle the code coverage context menu action.
699 """
700 itm = self.model().item(self.currentIndex())
701 fn = itm.fileName()
702 pfn = self.project.getMainScript(True)
703
704 files = []
705
706 if pfn is not None:
707 tpfn = Utilities.getTestFileName(pfn)
708 basename = os.path.splitext(pfn)[0]
709 tbasename = os.path.splitext(tpfn)[0]
710
711 f = "%s.coverage" % basename
712 tf = "%s.coverage" % tbasename
713 if os.path.isfile(f):
714 files.append(f)
715 if os.path.isfile(tf):
716 files.append(tf)
717
718 if fn is not None:
719 tfn = Utilities.getTestFileName(fn)
720 basename = os.path.splitext(fn)[0]
721 tbasename = os.path.splitext(tfn)[0]
722
723 f = "%s.coverage" % basename
724 tf = "%s.coverage" % tbasename
725 if os.path.isfile(f) and not f in files:
726 files.append(f)
727 if os.path.isfile(tf) and not tf in files:
728 files.append(tf)
729
730 if files:
731 if len(files) > 1:
732 pfn, ok = QInputDialog.getItem(\
733 None,
734 self.trUtf8("Code Coverage"),
735 self.trUtf8("Please select a coverage file"),
736 files,
737 0, False)
738 if not ok:
739 return
740 else:
741 pfn = files[0]
742 else:
743 return
744
745 self.codecoverage = PyCoverageDialog()
746 self.codecoverage.show()
747 self.codecoverage.start(pfn, fn)
748
749 def __showProfileData(self):
750 """
751 Private method to handle the show profile data context menu action.
752 """
753 itm = self.model().item(self.currentIndex())
754 fn = itm.fileName()
755 pfn = self.project.getMainScript(True)
756
757 files = []
758
759 if pfn is not None:
760 tpfn = Utilities.getTestFileName(pfn)
761 basename = os.path.splitext(pfn)[0]
762 tbasename = os.path.splitext(tpfn)[0]
763
764 f = "%s.profile" % basename
765 tf = "%s.profile" % tbasename
766 if os.path.isfile(f):
767 files.append(f)
768 if os.path.isfile(tf):
769 files.append(tf)
770
771 if fn is not None:
772 tfn = Utilities.getTestFileName(fn)
773 basename = os.path.splitext(fn)[0]
774 tbasename = os.path.splitext(tfn)[0]
775
776 f = "%s.profile" % basename
777 tf = "%s.profile" % tbasename
778 if os.path.isfile(f) and not f in files:
779 files.append(f)
780 if os.path.isfile(tf) and not tf in files:
781 files.append(tf)
782
783 if files:
784 if len(files) > 1:
785 pfn, ok = QInputDialog.getItem(\
786 None,
787 self.trUtf8("Profile Data"),
788 self.trUtf8("Please select a profile file"),
789 files,
790 0, False)
791 if not ok:
792 return
793 else:
794 pfn = files[0]
795 else:
796 return
797
798 self.profiledata = PyProfileDialog()
799 self.profiledata.show()
800 self.profiledata.start(pfn, fn)
801
802 ############################################################################
803 ## Methods for the Graphics submenu
804 ############################################################################
805
806 def __showContextMenuGraphics(self):
807 """
808 Private slot called before the checks menu is shown.
809 """
810 self.emit(SIGNAL("showMenu"), "Graphics", self.graphicsMenu)
811
812 def __showClassDiagram(self):
813 """
814 Private method to handle the class diagram context menu action.
815 """
816 itm = self.model().item(self.currentIndex())
817 try:
818 fn = itm.fileName()
819 except AttributeError:
820 fn = itm.dirName()
821 res = QMessageBox.question(None,
822 self.trUtf8("Class Diagram"),
823 self.trUtf8("""Include class attributes?"""),
824 QMessageBox.StandardButtons(\
825 QMessageBox.No | \
826 QMessageBox.Yes),
827 QMessageBox.Yes)
828 self.classDiagram = UMLClassDiagram(fn, self,
829 noAttrs = (res != QMessageBox.Yes))
830 self.classDiagram.show()
831
832 def __showImportsDiagram(self):
833 """
834 Private method to handle the imports diagram context menu action.
835 """
836 itm = self.model().item(self.currentIndex())
837 try:
838 fn = itm.fileName()
839 except AttributeError:
840 fn = itm.dirName()
841 package = os.path.isdir(fn) and fn or os.path.dirname(fn)
842 res = QMessageBox.question(None,
843 self.trUtf8("Imports Diagram"),
844 self.trUtf8("""Include imports from external modules?"""),
845 QMessageBox.StandardButtons(\
846 QMessageBox.No | \
847 QMessageBox.Yes),
848 QMessageBox.No)
849 self.importsDiagram = ImportsDiagram(package, self,
850 showExternalImports = (res == QMessageBox.Yes))
851 self.importsDiagram.show()
852
853 def __showPackageDiagram(self):
854 """
855 Private method to handle the package diagram context menu action.
856 """
857 itm = self.model().item(self.currentIndex())
858 try:
859 fn = itm.fileName()
860 except AttributeError:
861 fn = itm.dirName()
862 package = os.path.isdir(fn) and fn or os.path.dirname(fn)
863 res = QMessageBox.question(None,
864 self.trUtf8("Package Diagram"),
865 self.trUtf8("""Include class attributes?"""),
866 QMessageBox.StandardButtons(\
867 QMessageBox.No | \
868 QMessageBox.Yes),
869 QMessageBox.Yes)
870 self.packageDiagram = PackageDiagram(package, self,
871 noAttrs = (res != QMessageBox.Yes))
872 self.packageDiagram.show()
873
874 def __showApplicationDiagram(self):
875 """
876 Private method to handle the application diagram context menu action.
877 """
878 res = QMessageBox.question(None,
879 self.trUtf8("Application Diagram"),
880 self.trUtf8("""Include module names?"""),
881 QMessageBox.StandardButtons(\
882 QMessageBox.No | \
883 QMessageBox.Yes),
884 QMessageBox.Yes)
885 self.applicationDiagram = ApplicationDiagram(self.project, self,
886 noModules = (res != QMessageBox.Yes))
887 self.applicationDiagram.show()

eric ide

mercurial