11 |
11 |
12 from PyQt5.QtCore import QCoreApplication, QModelIndex |
12 from PyQt5.QtCore import QCoreApplication, QModelIndex |
13 |
13 |
14 from UI.BrowserModel import ( |
14 from UI.BrowserModel import ( |
15 BrowserModel, BrowserItem, BrowserClassItem, BrowserCodingItem, |
15 BrowserModel, BrowserItem, BrowserClassItem, BrowserCodingItem, |
16 BrowserGlobalsItem, BrowserImportsItem, BrowserImportItem |
16 BrowserGlobalsItem, BrowserImportsItem, BrowserImportItem, |
|
17 BrowserClassAttributesItem, BrowserMethodItem |
17 ) |
18 ) |
18 |
19 |
19 |
20 |
20 class EditorOutlineModel(BrowserModel): |
21 class EditorOutlineModel(BrowserModel): |
21 """ |
22 """ |
23 """ |
24 """ |
24 SupportedLanguages = ( |
25 SupportedLanguages = ( |
25 "IDL", "JavaScript", "Protocol", "Python3", "MicroPython", "Ruby", |
26 "IDL", "JavaScript", "Protocol", "Python3", "MicroPython", "Ruby", |
26 ) |
27 ) |
27 |
28 |
28 def __init__(self, editor): |
29 def __init__(self, editor, populate=True): |
29 """ |
30 """ |
30 Constructor |
31 Constructor |
31 |
32 |
32 @param editor reference to the editor containing the source text |
33 @param editor reference to the editor containing the source text |
33 @type Editor |
34 @type Editor |
|
35 @param populate flag indicating to populate the outline |
|
36 @type bool |
34 """ |
37 """ |
35 super(EditorOutlineModel, self).__init__(nopopulate=True) |
38 super(EditorOutlineModel, self).__init__(nopopulate=True) |
36 |
39 |
37 self.__editor = editor |
40 self.__editor = editor |
38 |
41 |
39 self.__populated = False |
42 self.__populated = False |
40 |
43 |
41 rootData = QCoreApplication.translate("EditorOutlineModel", "Name") |
44 rootData = QCoreApplication.translate("EditorOutlineModel", "Name") |
42 self.rootItem = BrowserItem(None, rootData) |
45 self.rootItem = BrowserItem(None, rootData) |
43 |
46 |
44 self.__populateModel() |
47 if populate: |
|
48 self.__populateModel() |
45 |
49 |
46 def __populateModel(self, repopulate=False): |
50 def __populateModel(self, repopulate=False): |
47 """ |
51 """ |
48 Private slot to populate the model. |
52 Private slot to populate the model. |
49 |
53 |
53 self.__filename = self.__editor.getFileName() |
57 self.__filename = self.__editor.getFileName() |
54 self.__module = os.path.basename(self.__filename) |
58 self.__module = os.path.basename(self.__filename) |
55 |
59 |
56 language = self.__editor.getLanguage() |
60 language = self.__editor.getLanguage() |
57 if language in EditorOutlineModel.SupportedLanguages: |
61 if language in EditorOutlineModel.SupportedLanguages: |
58 if language in ("Python3", "MicroPython"): |
62 if language == "IDL": |
|
63 from Utilities.ClassBrowsers import idlclbr |
|
64 dictionary = idlclbr.scan( |
|
65 self.__editor.text(), self.__filename, self.__module) |
|
66 idlclbr._modules.clear() |
|
67 elif language == "ProtoBuf": |
|
68 from Utilities.ClassBrowsers import protoclbr |
|
69 dictionary = protoclbr.scan( |
|
70 self.__editor.text(), self.__filename, self.__module) |
|
71 protoclbr._modules.clear() |
|
72 elif language == "Ruby": |
|
73 from Utilities.ClassBrowsers import rbclbr |
|
74 dictionary = rbclbr.scan( |
|
75 self.__editor.text(), self.__filename, self.__module) |
|
76 rbclbr._modules.clear() |
|
77 elif language == "JavaScript": |
|
78 from Utilities.ClassBrowsers import jsclbr |
|
79 dictionary = jsclbr.scan( |
|
80 self.__editor.text(), self.__filename, self.__module) |
|
81 jsclbr._modules.clear() |
|
82 elif language in ("Python3", "MicroPython"): |
59 from Utilities.ClassBrowsers import pyclbr |
83 from Utilities.ClassBrowsers import pyclbr |
60 dictionary = pyclbr.scan(self.__editor.text(), self.__filename, |
84 dictionary = pyclbr.scan( |
61 self.__module) |
85 self.__editor.text(), self.__filename, self.__module) |
62 pyclbr._modules.clear() |
86 pyclbr._modules.clear() |
63 |
87 |
64 keys = list(dictionary.keys()) |
88 keys = list(dictionary.keys()) |
65 if len(keys) > 0: |
89 if len(keys) > 0: |
66 parentItem = self.rootItem |
90 parentItem = self.rootItem |
85 if "@@Coding@@" in keys: |
109 if "@@Coding@@" in keys: |
86 node = BrowserCodingItem( |
110 node = BrowserCodingItem( |
87 parentItem, |
111 parentItem, |
88 QCoreApplication.translate( |
112 QCoreApplication.translate( |
89 "EditorOutlineModel", "Coding: {0}") |
113 "EditorOutlineModel", "Coding: {0}") |
90 .format(dictionary["@@Coding@@"].coding)) |
114 .format(dictionary["@@Coding@@"].coding), |
|
115 dictionary["@@Coding@@"].linenumber) |
91 self._addItem(node, parentItem) |
116 self._addItem(node, parentItem) |
92 if "@@Globals@@" in keys: |
117 if "@@Globals@@" in keys: |
93 node = BrowserGlobalsItem( |
118 node = BrowserGlobalsItem( |
94 parentItem, |
119 parentItem, |
95 dictionary["@@Globals@@"].globals, |
120 dictionary["@@Globals@@"].globals, |
161 |
186 |
162 @return file name of the editor |
187 @return file name of the editor |
163 @rtype str |
188 @rtype str |
164 """ |
189 """ |
165 return self.__filename |
190 return self.__filename |
|
191 |
|
192 def itemIndexByLine(self, lineno): |
|
193 """ |
|
194 Public method to find an item's index given a line number. |
|
195 |
|
196 @param lineno one based line number of the item |
|
197 @type int |
|
198 @return index of the item found |
|
199 @rtype QModelIndex |
|
200 """ |
|
201 def findItem(lineno, parent): |
|
202 """ |
|
203 Function to iteratively search for an item containing the given |
|
204 line. |
|
205 |
|
206 @param lineno one based line number of the item |
|
207 @type int |
|
208 @param parent reference to the parent item |
|
209 @type BrowserItem |
|
210 @return found item or None |
|
211 @rtype BrowserItem |
|
212 """ |
|
213 if not parent.isPopulated(): |
|
214 if parent.isLazyPopulated(): |
|
215 self.populateItem(parent) |
|
216 else: |
|
217 return None |
|
218 for child in parent.children(): |
|
219 if isinstance(child, BrowserClassAttributesItem): |
|
220 itm = findItem(lineno, child) |
|
221 if itm is not None: |
|
222 return itm |
|
223 elif isinstance(child, (BrowserClassItem, BrowserMethodItem)): |
|
224 start, end = child.boundaries() |
|
225 if end == -1: |
|
226 end = 1000000 # assume end of file |
|
227 if start <= lineno <= end: |
|
228 itm = findItem(lineno, child) |
|
229 if itm is not None: |
|
230 return itm |
|
231 else: |
|
232 return child |
|
233 elif hasattr(child, "linenos"): |
|
234 if lineno in child.linenos(): |
|
235 return child |
|
236 elif hasattr(child, "lineno"): |
|
237 if lineno == child.lineno(): |
|
238 return child |
|
239 else: |
|
240 return None |
|
241 |
|
242 if self.__populated: |
|
243 for rootChild in self.rootItem.children(): |
|
244 itm = None |
|
245 if isinstance(rootChild, BrowserClassItem): |
|
246 start, end = rootChild.boundaries() |
|
247 if end == -1: |
|
248 end = 1000000 # assume end of file |
|
249 if start <= lineno <= end: |
|
250 itm = findItem(lineno, rootChild) |
|
251 if itm is None: |
|
252 itm = rootChild |
|
253 elif isinstance(rootChild, |
|
254 (BrowserImportsItem, BrowserGlobalsItem)): |
|
255 itm = findItem(lineno, rootChild) |
|
256 elif ( |
|
257 isinstance(rootChild, BrowserCodingItem) and |
|
258 lineno == rootChild.lineno() |
|
259 ): |
|
260 itm = rootChild |
|
261 if itm is not None: |
|
262 return self.createIndex(itm.row(), 0, itm) |
|
263 else: |
|
264 return QModelIndex() |
|
265 |
|
266 return QModelIndex() |