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