|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2002 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the project browser part of the eric6 UI. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals |
|
11 |
|
12 from PyQt5.QtCore import Qt |
|
13 from PyQt5.QtGui import QColor |
|
14 from PyQt5.QtWidgets import QApplication |
|
15 |
|
16 from E5Gui.E5TabWidget import E5TabWidget |
|
17 from E5Gui.E5Led import E5ClickableLed |
|
18 |
|
19 import UI.PixmapCache |
|
20 import Preferences |
|
21 |
|
22 from .ProjectBrowserFlags import SourcesBrowserFlag, FormsBrowserFlag, \ |
|
23 ResourcesBrowserFlag, TranslationsBrowserFlag, InterfacesBrowserFlag, \ |
|
24 OthersBrowserFlag, ProtocolsBrowserFlag, AllBrowsersFlag |
|
25 |
|
26 |
|
27 class ProjectBrowser(E5TabWidget): |
|
28 """ |
|
29 Class implementing the project browser part of the eric6 UI. |
|
30 |
|
31 It generates a widget with up to seven tabs. The individual tabs contain |
|
32 the project sources browser, the project forms browser, |
|
33 the project resources browser, the project translations browser, |
|
34 the project interfaces (IDL) browser and a browser for stuff, |
|
35 that doesn't fit these categories. Optionally it contains an additional |
|
36 tab with the file system browser. |
|
37 """ |
|
38 def __init__(self, project, parent=None): |
|
39 """ |
|
40 Constructor |
|
41 |
|
42 @param project reference to the project object |
|
43 @param parent parent widget (QWidget) |
|
44 """ |
|
45 E5TabWidget.__init__(self, parent) |
|
46 self.project = project |
|
47 |
|
48 self.setWindowIcon(UI.PixmapCache.getIcon("eric.png")) |
|
49 |
|
50 self.setUsesScrollButtons(True) |
|
51 |
|
52 self.vcsStatusIndicator = E5ClickableLed(self) |
|
53 self.setCornerWidget(self.vcsStatusIndicator, Qt.TopLeftCorner) |
|
54 self.vcsStatusIndicator.clicked.connect( |
|
55 self.__vcsStatusIndicatorClicked) |
|
56 self.vcsStatusColorNames = { |
|
57 "A": "VcsAdded", |
|
58 "M": "VcsModified", |
|
59 "O": "VcsRemoved", |
|
60 "R": "VcsReplaced", |
|
61 "U": "VcsUpdate", |
|
62 "Z": "VcsConflict", |
|
63 } |
|
64 self.vcsStatusText = { |
|
65 " ": self.tr("up to date"), |
|
66 "A": self.tr("files added"), |
|
67 "M": self.tr("local modifications"), |
|
68 "O": self.tr("files removed"), |
|
69 "R": self.tr("files replaced"), |
|
70 "U": self.tr("update required"), |
|
71 "Z": self.tr("conflict"), |
|
72 } |
|
73 self.__vcsStateChanged(" ") |
|
74 |
|
75 # step 1: create all the individual browsers |
|
76 from .ProjectSourcesBrowser import ProjectSourcesBrowser |
|
77 from .ProjectFormsBrowser import ProjectFormsBrowser |
|
78 from .ProjectTranslationsBrowser import ProjectTranslationsBrowser |
|
79 from .ProjectResourcesBrowser import ProjectResourcesBrowser |
|
80 from .ProjectInterfacesBrowser import ProjectInterfacesBrowser |
|
81 from .ProjectOthersBrowser import ProjectOthersBrowser |
|
82 from .ProjectProtocolsBrowser import ProjectProtocolsBrowser |
|
83 # sources browser |
|
84 self.psBrowser = ProjectSourcesBrowser(self.project) |
|
85 # forms browser |
|
86 self.pfBrowser = ProjectFormsBrowser(self.project) |
|
87 # resources browser |
|
88 self.prBrowser = ProjectResourcesBrowser(self.project) |
|
89 # translations browser |
|
90 self.ptBrowser = ProjectTranslationsBrowser(self.project) |
|
91 # interfaces (IDL) browser |
|
92 self.piBrowser = ProjectInterfacesBrowser(self.project) |
|
93 # protocols (protobuf) browser |
|
94 self.ppBrowser = ProjectProtocolsBrowser(self.project) |
|
95 # others browser |
|
96 self.poBrowser = ProjectOthersBrowser(self.project) |
|
97 |
|
98 # step 2: connect all the browsers |
|
99 # connect the sources browser |
|
100 self.project.projectClosed.connect(self.psBrowser._projectClosed) |
|
101 self.project.projectOpened.connect(self.psBrowser._projectOpened) |
|
102 self.project.newProject.connect(self.psBrowser._newProject) |
|
103 self.project.reinitVCS.connect(self.psBrowser._initMenusAndVcs) |
|
104 self.project.projectPropertiesChanged.connect( |
|
105 self.psBrowser._initMenusAndVcs) |
|
106 |
|
107 # connect the forms browser |
|
108 self.project.projectClosed.connect(self.pfBrowser._projectClosed) |
|
109 self.project.projectOpened.connect(self.pfBrowser._projectOpened) |
|
110 self.project.newProject.connect(self.pfBrowser._newProject) |
|
111 self.project.reinitVCS.connect(self.pfBrowser._initMenusAndVcs) |
|
112 self.project.projectPropertiesChanged.connect( |
|
113 self.pfBrowser._initMenusAndVcs) |
|
114 |
|
115 # connect the resources browser |
|
116 self.project.projectClosed.connect(self.prBrowser._projectClosed) |
|
117 self.project.projectOpened.connect(self.prBrowser._projectOpened) |
|
118 self.project.newProject.connect(self.prBrowser._newProject) |
|
119 self.project.reinitVCS.connect(self.prBrowser._initMenusAndVcs) |
|
120 self.project.projectPropertiesChanged.connect( |
|
121 self.prBrowser._initMenusAndVcs) |
|
122 |
|
123 # connect the translations browser |
|
124 self.project.projectClosed.connect(self.ptBrowser._projectClosed) |
|
125 self.project.projectOpened.connect(self.ptBrowser._projectOpened) |
|
126 self.project.newProject.connect(self.ptBrowser._newProject) |
|
127 self.project.reinitVCS.connect(self.ptBrowser._initMenusAndVcs) |
|
128 self.project.projectPropertiesChanged.connect( |
|
129 self.ptBrowser._initMenusAndVcs) |
|
130 |
|
131 # connect the interfaces (IDL) browser |
|
132 self.project.projectClosed.connect(self.piBrowser._projectClosed) |
|
133 self.project.projectOpened.connect(self.piBrowser._projectOpened) |
|
134 self.project.newProject.connect(self.piBrowser._newProject) |
|
135 self.project.reinitVCS.connect(self.piBrowser._initMenusAndVcs) |
|
136 self.project.projectPropertiesChanged.connect( |
|
137 self.piBrowser._initMenusAndVcs) |
|
138 |
|
139 # connect the protocols (protobuf) browser |
|
140 self.project.projectClosed.connect(self.ppBrowser._projectClosed) |
|
141 self.project.projectOpened.connect(self.ppBrowser._projectOpened) |
|
142 self.project.newProject.connect(self.ppBrowser._newProject) |
|
143 self.project.reinitVCS.connect(self.ppBrowser._initMenusAndVcs) |
|
144 self.project.projectPropertiesChanged.connect( |
|
145 self.ppBrowser._initMenusAndVcs) |
|
146 |
|
147 # connect the others browser |
|
148 self.project.projectClosed.connect(self.poBrowser._projectClosed) |
|
149 self.project.projectOpened.connect(self.poBrowser._projectOpened) |
|
150 self.project.newProject.connect(self.poBrowser._newProject) |
|
151 self.project.reinitVCS.connect(self.poBrowser._initMenusAndVcs) |
|
152 self.project.projectPropertiesChanged.connect( |
|
153 self.poBrowser._initMenusAndVcs) |
|
154 |
|
155 # add signal connection to ourselves |
|
156 self.project.projectOpened.connect(self.__projectOpened) |
|
157 self.project.projectClosed.connect(self.__projectClosed) |
|
158 self.project.newProject.connect(self.__newProject) |
|
159 self.project.projectPropertiesChanged.connect( |
|
160 self.__projectPropertiesChanged) |
|
161 self.currentChanged.connect(self.__currentChanged) |
|
162 self.project.getModel().vcsStateChanged.connect(self.__vcsStateChanged) |
|
163 |
|
164 self.__currentBrowsersFlags = 0 |
|
165 self.__projectPropertiesChanged() |
|
166 self.setCurrentIndex(0) |
|
167 |
|
168 def __setBrowsersAvailable(self, browserFlags): |
|
169 """ |
|
170 Private method to add selected browsers to the project browser. |
|
171 |
|
172 @param browserFlags flags indicating the browsers to add (integer) |
|
173 """ |
|
174 # step 1: remove all tabs |
|
175 while self.count() > 0: |
|
176 self.removeTab(0) |
|
177 |
|
178 # step 2: add browsers |
|
179 if browserFlags & SourcesBrowserFlag: |
|
180 index = self.addTab( |
|
181 self.psBrowser, |
|
182 UI.PixmapCache.getIcon("projectSources.png"), '') |
|
183 self.setTabToolTip(index, self.psBrowser.windowTitle()) |
|
184 |
|
185 if browserFlags & FormsBrowserFlag: |
|
186 index = self.addTab( |
|
187 self.pfBrowser, |
|
188 UI.PixmapCache.getIcon("projectForms.png"), '') |
|
189 self.setTabToolTip(index, self.pfBrowser.windowTitle()) |
|
190 |
|
191 if browserFlags & ResourcesBrowserFlag: |
|
192 index = self.addTab( |
|
193 self.prBrowser, |
|
194 UI.PixmapCache.getIcon("projectResources.png"), '') |
|
195 self.setTabToolTip(index, self.prBrowser.windowTitle()) |
|
196 |
|
197 if browserFlags & TranslationsBrowserFlag: |
|
198 index = self.addTab( |
|
199 self.ptBrowser, |
|
200 UI.PixmapCache.getIcon("projectTranslations.png"), '') |
|
201 self.setTabToolTip(index, self.ptBrowser.windowTitle()) |
|
202 |
|
203 if browserFlags & InterfacesBrowserFlag: |
|
204 index = self.addTab( |
|
205 self.piBrowser, |
|
206 UI.PixmapCache.getIcon("projectInterfaces.png"), '') |
|
207 self.setTabToolTip(index, self.piBrowser.windowTitle()) |
|
208 |
|
209 if browserFlags & ProtocolsBrowserFlag: |
|
210 index = self.addTab( |
|
211 self.ppBrowser, |
|
212 UI.PixmapCache.getIcon("protobuf.png"), '') |
|
213 self.setTabToolTip(index, self.ppBrowser.windowTitle()) |
|
214 |
|
215 if browserFlags & OthersBrowserFlag: |
|
216 index = self.addTab( |
|
217 self.poBrowser, |
|
218 UI.PixmapCache.getIcon("projectOthers.png"), '') |
|
219 self.setTabToolTip(index, self.poBrowser.windowTitle()) |
|
220 |
|
221 QApplication.processEvents() |
|
222 |
|
223 def __currentChanged(self, index): |
|
224 """ |
|
225 Private slot to handle the currentChanged(int) signal. |
|
226 |
|
227 @param index index of the tab (integer) |
|
228 """ |
|
229 if index > -1: |
|
230 browser = self.widget(index) |
|
231 if browser is not None: |
|
232 browser.layoutDisplay() |
|
233 |
|
234 def __projectOpened(self): |
|
235 """ |
|
236 Private slot to handle the projectOpened signal. |
|
237 """ |
|
238 self.__projectPropertiesChanged() |
|
239 self.setCurrentIndex(0) |
|
240 self.__vcsStateChanged(" ") |
|
241 |
|
242 def __projectClosed(self): |
|
243 """ |
|
244 Private slot to handle the projectClosed signal. |
|
245 """ |
|
246 self.__projectPropertiesChanged() |
|
247 self.setCurrentIndex(0) |
|
248 self.__setSourcesIcon() |
|
249 self.__vcsStateChanged(" ") |
|
250 |
|
251 def __newProject(self): |
|
252 """ |
|
253 Private slot to handle the newProject signal. |
|
254 """ |
|
255 self.setCurrentIndex(0) |
|
256 self.__projectPropertiesChanged() |
|
257 |
|
258 def __projectPropertiesChanged(self): |
|
259 """ |
|
260 Private slot to handle the projectPropertiesChanged signal. |
|
261 """ |
|
262 if self.project.isOpen(): |
|
263 flags = Preferences.getProjectBrowserFlags( |
|
264 self.project.getProjectType()) |
|
265 else: |
|
266 flags = AllBrowsersFlag |
|
267 |
|
268 if flags != self.__currentBrowsersFlags: |
|
269 self.__currentBrowsersFlags = flags |
|
270 self.__setBrowsersAvailable(flags) |
|
271 |
|
272 endIndex = self.count() |
|
273 for index in range(endIndex): |
|
274 self.setTabEnabled(index, self.project.isOpen()) |
|
275 |
|
276 self.__setSourcesIcon() |
|
277 |
|
278 def __setSourcesIcon(self): |
|
279 """ |
|
280 Private method to set the right icon for the sources browser tab. |
|
281 """ |
|
282 if not self.project.isOpen(): |
|
283 icon = UI.PixmapCache.getIcon("projectSources.png") |
|
284 else: |
|
285 if self.project.getProjectLanguage() in \ |
|
286 ["Python", "Python2", "Python3"]: |
|
287 if self.project.isMixedLanguageProject(): |
|
288 icon = UI.PixmapCache.getIcon("projectSourcesPyMixed.png") |
|
289 else: |
|
290 icon = UI.PixmapCache.getIcon("projectSourcesPy.png") |
|
291 elif self.project.getProjectLanguage() == "Ruby": |
|
292 if self.project.isMixedLanguageProject(): |
|
293 icon = UI.PixmapCache.getIcon("projectSourcesRbMixed.png") |
|
294 else: |
|
295 icon = UI.PixmapCache.getIcon("projectSourcesRb.png") |
|
296 elif self.project.getProjectLanguage() == "JavaScript": |
|
297 icon = UI.PixmapCache.getIcon("projectSourcesJavaScript.png") |
|
298 else: |
|
299 icon = UI.PixmapCache.getIcon("projectSources.png") |
|
300 self.setTabIcon(self.indexOf(self.psBrowser), icon) |
|
301 |
|
302 def handleEditorChanged(self, fn): |
|
303 """ |
|
304 Public slot to handle the editorChanged signal. |
|
305 |
|
306 @param fn filename of the changed file (string) |
|
307 """ |
|
308 if Preferences.getProject("FollowEditor"): |
|
309 if self.project.isProjectSource(fn): |
|
310 self.psBrowser.selectFile(fn) |
|
311 elif self.project.isProjectForm(fn): |
|
312 self.pfBrowser.selectFile(fn) |
|
313 elif self.project.isProjectInterface(fn): |
|
314 self.piBrowser.selectFile(fn) |
|
315 elif self.project.isProjectProtocol(fn): |
|
316 self.ppBrowser.selectFile(fn) |
|
317 elif self.project.isProjectProtocol(fn): |
|
318 self.ppBrowser.selectFile(fn) |
|
319 |
|
320 def handleEditorLineChanged(self, fn, lineno): |
|
321 """ |
|
322 Public slot to handle the editorLineChanged signal. |
|
323 |
|
324 @param fn filename of the changed file (string) |
|
325 @param lineno one based line number of the item (integer) |
|
326 """ |
|
327 if Preferences.getProject("FollowEditor") and \ |
|
328 Preferences.getProject("FollowCursorLine"): |
|
329 if self.project.isProjectSource(fn): |
|
330 self.psBrowser.selectFileLine(fn, lineno) |
|
331 |
|
332 def getProjectBrowsers(self): |
|
333 """ |
|
334 Public method to get references to the individual project browsers. |
|
335 |
|
336 @return list of references to project browsers |
|
337 """ |
|
338 return [self.psBrowser, self.pfBrowser, self.prBrowser, |
|
339 self.ptBrowser, self.piBrowser, self.ppBrowser, |
|
340 self.poBrowser] |
|
341 |
|
342 def getProjectBrowser(self, name): |
|
343 """ |
|
344 Public method to get a reference to the named project browser. |
|
345 |
|
346 @param name name of the requested project browser (string). |
|
347 Valid names are "sources, forms, resources, translations, |
|
348 interfaces, protocols, others". |
|
349 @return reference to the requested browser or None |
|
350 """ |
|
351 if name == "sources": |
|
352 return self.psBrowser |
|
353 elif name == "forms": |
|
354 return self.pfBrowser |
|
355 elif name == "resources": |
|
356 return self.prBrowser |
|
357 elif name == "translations": |
|
358 return self.ptBrowser |
|
359 elif name == "interfaces": |
|
360 return self.piBrowser |
|
361 elif name == "protocols": |
|
362 return self.ppBrowser |
|
363 elif name == "others": |
|
364 return self.poBrowser |
|
365 else: |
|
366 return None |
|
367 |
|
368 def getProjectBrowserNames(self): |
|
369 """ |
|
370 Public method to get the names of the various project browsers. |
|
371 |
|
372 @return list of project browser names (list of string) |
|
373 """ |
|
374 return ["sources", "forms", "resources", |
|
375 "translations", "interfaces", "protocols", "others"] |
|
376 |
|
377 def handlePreferencesChanged(self): |
|
378 """ |
|
379 Public slot used to handle the preferencesChanged signal. |
|
380 """ |
|
381 self.__projectPropertiesChanged() |
|
382 self.__vcsStateChanged(self.currentVcsStatus) |
|
383 |
|
384 def __vcsStateChanged(self, state): |
|
385 """ |
|
386 Private slot to handle a change in the vcs state. |
|
387 |
|
388 @param state new vcs state (string) |
|
389 """ |
|
390 self.currentVcsStatus = state |
|
391 if state == " " or state not in self.vcsStatusColorNames: |
|
392 self.vcsStatusIndicator.setColor(QColor(Qt.lightGray)) |
|
393 else: |
|
394 self.vcsStatusIndicator.setColor( |
|
395 Preferences.getProjectBrowserColour( |
|
396 self.vcsStatusColorNames[state])) |
|
397 if state not in self.vcsStatusText: |
|
398 self.vcsStatusIndicator.setToolTip(self.tr("unknown status")) |
|
399 else: |
|
400 self.vcsStatusIndicator.setToolTip(self.vcsStatusText[state]) |
|
401 |
|
402 def __vcsStatusIndicatorClicked(self, pos): |
|
403 """ |
|
404 Private slot to react upon clicks on the VCS indicator LED. |
|
405 |
|
406 @param pos position of the click (QPoint) |
|
407 """ |
|
408 vcs = self.project.getVcs() |
|
409 if vcs: |
|
410 if self.currentVcsStatus == " ": |
|
411 # call log browser dialog |
|
412 vcs.vcsLogBrowser(self.project.getProjectPath()) |
|
413 else: |
|
414 # call status dialog |
|
415 vcs.vcsStatus(self.project.getProjectPath()) |