11 import contextlib |
11 import contextlib |
12 |
12 |
13 from PyQt6.QtCore import QCoreApplication, QModelIndex |
13 from PyQt6.QtCore import QCoreApplication, QModelIndex |
14 |
14 |
15 from UI.BrowserModel import ( |
15 from UI.BrowserModel import ( |
16 BrowserModel, BrowserItem, BrowserClassItem, BrowserCodingItem, |
16 BrowserModel, |
17 BrowserGlobalsItem, BrowserImportsItem, BrowserImportItem, |
17 BrowserItem, |
18 BrowserClassAttributesItem, BrowserMethodItem |
18 BrowserClassItem, |
|
19 BrowserCodingItem, |
|
20 BrowserGlobalsItem, |
|
21 BrowserImportsItem, |
|
22 BrowserImportItem, |
|
23 BrowserClassAttributesItem, |
|
24 BrowserMethodItem, |
19 ) |
25 ) |
20 |
26 |
21 import Preferences |
27 import Preferences |
22 |
28 |
23 |
29 |
24 class EditorOutlineModel(BrowserModel): |
30 class EditorOutlineModel(BrowserModel): |
25 """ |
31 """ |
26 Class implementing the editor outline model. |
32 Class implementing the editor outline model. |
27 """ |
33 """ |
|
34 |
28 SupportedLanguages = ( |
35 SupportedLanguages = ( |
29 "IDL", "JavaScript", "Protocol", "Python3", "MicroPython", "Cython", |
36 "IDL", |
|
37 "JavaScript", |
|
38 "Protocol", |
|
39 "Python3", |
|
40 "MicroPython", |
|
41 "Cython", |
30 "Ruby", |
42 "Ruby", |
31 ) |
43 ) |
32 |
44 |
33 def __init__(self, editor, populate=True): |
45 def __init__(self, editor, populate=True): |
34 """ |
46 """ |
35 Constructor |
47 Constructor |
36 |
48 |
37 @param editor reference to the editor containing the source text |
49 @param editor reference to the editor containing the source text |
38 @type Editor |
50 @type Editor |
39 @param populate flag indicating to populate the outline |
51 @param populate flag indicating to populate the outline |
40 @type bool |
52 @type bool |
41 """ |
53 """ |
42 super().__init__(nopopulate=True) |
54 super().__init__(nopopulate=True) |
43 |
55 |
44 self.__editor = editor |
56 self.__editor = editor |
45 |
57 |
46 self.__populated = False |
58 self.__populated = False |
47 |
59 |
48 rootData = QCoreApplication.translate("EditorOutlineModel", "Name") |
60 rootData = QCoreApplication.translate("EditorOutlineModel", "Name") |
49 self.rootItem = BrowserItem(None, rootData) |
61 self.rootItem = BrowserItem(None, rootData) |
50 |
62 |
51 if populate: |
63 if populate: |
52 self.__populateModel() |
64 self.__populateModel() |
53 |
65 |
54 def __populateModel(self, repopulate=False): |
66 def __populateModel(self, repopulate=False): |
55 """ |
67 """ |
56 Private slot to populate the model. |
68 Private slot to populate the model. |
57 |
69 |
58 @param repopulate flag indicating a repopulation |
70 @param repopulate flag indicating a repopulation |
59 @type bool |
71 @type bool |
60 """ |
72 """ |
61 self.__filename = self.__editor.getFileName() |
73 self.__filename = self.__editor.getFileName() |
62 self.__module = os.path.basename(self.__filename) |
74 self.__module = os.path.basename(self.__filename) |
63 |
75 |
64 language = self.__editor.getLanguage() |
76 language = self.__editor.getLanguage() |
65 if language in EditorOutlineModel.SupportedLanguages: |
77 if language in EditorOutlineModel.SupportedLanguages: |
66 if language == "IDL": |
78 if language == "IDL": |
67 from Utilities.ClassBrowsers import idlclbr |
79 from Utilities.ClassBrowsers import idlclbr |
|
80 |
68 dictionary = idlclbr.scan( |
81 dictionary = idlclbr.scan( |
69 self.__editor.text(), self.__filename, self.__module) |
82 self.__editor.text(), self.__filename, self.__module |
|
83 ) |
70 idlclbr._modules.clear() |
84 idlclbr._modules.clear() |
71 elif language == "Protocol": |
85 elif language == "Protocol": |
72 from Utilities.ClassBrowsers import protoclbr |
86 from Utilities.ClassBrowsers import protoclbr |
|
87 |
73 dictionary = protoclbr.scan( |
88 dictionary = protoclbr.scan( |
74 self.__editor.text(), self.__filename, self.__module) |
89 self.__editor.text(), self.__filename, self.__module |
|
90 ) |
75 protoclbr._modules.clear() |
91 protoclbr._modules.clear() |
76 elif language == "Ruby": |
92 elif language == "Ruby": |
77 from Utilities.ClassBrowsers import rbclbr |
93 from Utilities.ClassBrowsers import rbclbr |
|
94 |
78 dictionary = rbclbr.scan( |
95 dictionary = rbclbr.scan( |
79 self.__editor.text(), self.__filename, self.__module) |
96 self.__editor.text(), self.__filename, self.__module |
|
97 ) |
80 rbclbr._modules.clear() |
98 rbclbr._modules.clear() |
81 elif language == "JavaScript": |
99 elif language == "JavaScript": |
82 from Utilities.ClassBrowsers import jsclbr |
100 from Utilities.ClassBrowsers import jsclbr |
|
101 |
83 dictionary = jsclbr.scan( |
102 dictionary = jsclbr.scan( |
84 self.__editor.text(), self.__filename, self.__module) |
103 self.__editor.text(), self.__filename, self.__module |
|
104 ) |
85 jsclbr._modules.clear() |
105 jsclbr._modules.clear() |
86 elif language in ("Python3", "MicroPython", "Cython"): |
106 elif language in ("Python3", "MicroPython", "Cython"): |
87 from Utilities.ClassBrowsers import pyclbr |
107 from Utilities.ClassBrowsers import pyclbr |
|
108 |
88 dictionary = pyclbr.scan( |
109 dictionary = pyclbr.scan( |
89 self.__editor.text(), self.__filename, self.__module) |
110 self.__editor.text(), self.__filename, self.__module |
|
111 ) |
90 pyclbr._modules.clear() |
112 pyclbr._modules.clear() |
91 |
113 |
92 keys = list(dictionary.keys()) |
114 keys = list(dictionary.keys()) |
93 if len(keys) > 0: |
115 if len(keys) > 0: |
94 parentItem = self.rootItem |
116 parentItem = self.rootItem |
95 |
117 |
96 if repopulate: |
118 if repopulate: |
97 last = len(keys) - 1 |
119 last = len(keys) - 1 |
98 if ( |
120 if "@@Coding@@" in keys and not Preferences.getEditor( |
99 "@@Coding@@" in keys and |
121 "SourceOutlineShowCoding" |
100 not Preferences.getEditor("SourceOutlineShowCoding") |
|
101 ): |
122 ): |
102 last -= 1 |
123 last -= 1 |
103 self.beginInsertRows(QModelIndex(), 0, last) |
124 self.beginInsertRows(QModelIndex(), 0, last) |
104 |
125 |
105 for key in keys: |
126 for key in keys: |
106 if key.startswith("@@"): |
127 if key.startswith("@@"): |
107 # special treatment done later |
128 # special treatment done later |
108 continue |
129 continue |
109 cl = dictionary[key] |
130 cl = dictionary[key] |
110 with contextlib.suppress(AttributeError): |
131 with contextlib.suppress(AttributeError): |
111 if cl.module == self.__module: |
132 if cl.module == self.__module: |
112 node = BrowserClassItem( |
133 node = BrowserClassItem(parentItem, cl, self.__filename) |
113 parentItem, cl, self.__filename) |
|
114 self._addItem(node, parentItem) |
134 self._addItem(node, parentItem) |
115 if ( |
135 if "@@Coding@@" in keys and Preferences.getEditor( |
116 "@@Coding@@" in keys and |
136 "SourceOutlineShowCoding" |
117 Preferences.getEditor("SourceOutlineShowCoding") |
|
118 ): |
137 ): |
119 node = BrowserCodingItem( |
138 node = BrowserCodingItem( |
120 parentItem, |
139 parentItem, |
121 QCoreApplication.translate( |
140 QCoreApplication.translate( |
122 "EditorOutlineModel", "Coding: {0}") |
141 "EditorOutlineModel", "Coding: {0}" |
123 .format(dictionary["@@Coding@@"].coding), |
142 ).format(dictionary["@@Coding@@"].coding), |
124 dictionary["@@Coding@@"].linenumber) |
143 dictionary["@@Coding@@"].linenumber, |
|
144 ) |
125 self._addItem(node, parentItem) |
145 self._addItem(node, parentItem) |
126 if "@@Globals@@" in keys: |
146 if "@@Globals@@" in keys: |
127 node = BrowserGlobalsItem( |
147 node = BrowserGlobalsItem( |
128 parentItem, |
148 parentItem, |
129 dictionary["@@Globals@@"].globals, |
149 dictionary["@@Globals@@"].globals, |
130 QCoreApplication.translate( |
150 QCoreApplication.translate("EditorOutlineModel", "Globals"), |
131 "EditorOutlineModel", "Globals")) |
151 ) |
132 self._addItem(node, parentItem) |
152 self._addItem(node, parentItem) |
133 if "@@Import@@" in keys or "@@ImportFrom@@" in keys: |
153 if "@@Import@@" in keys or "@@ImportFrom@@" in keys: |
134 node = BrowserImportsItem( |
154 node = BrowserImportsItem( |
135 parentItem, |
155 parentItem, |
136 QCoreApplication.translate( |
156 QCoreApplication.translate("EditorOutlineModel", "Imports"), |
137 "EditorOutlineModel", "Imports")) |
157 ) |
138 self._addItem(node, parentItem) |
158 self._addItem(node, parentItem) |
139 if "@@Import@@" in keys: |
159 if "@@Import@@" in keys: |
140 for importedModule in ( |
160 for importedModule in ( |
141 dictionary["@@Import@@"].getImports().values() |
161 dictionary["@@Import@@"].getImports().values() |
142 ): |
162 ): |
143 m_node = BrowserImportItem( |
163 m_node = BrowserImportItem( |
144 node, |
164 node, |
145 importedModule.importedModuleName, |
165 importedModule.importedModuleName, |
146 importedModule.file, |
166 importedModule.file, |
147 importedModule.linenos) |
167 importedModule.linenos, |
|
168 ) |
148 self._addItem(m_node, node) |
169 self._addItem(m_node, node) |
149 for importedName, linenos in ( |
170 for ( |
150 importedModule.importedNames.items() |
171 importedName, |
151 ): |
172 linenos, |
|
173 ) in importedModule.importedNames.items(): |
152 mn_node = BrowserImportItem( |
174 mn_node = BrowserImportItem( |
153 m_node, |
175 m_node, |
154 importedName, |
176 importedName, |
155 importedModule.file, |
177 importedModule.file, |
156 linenos, |
178 linenos, |
157 isModule=False) |
179 isModule=False, |
|
180 ) |
158 self._addItem(mn_node, m_node) |
181 self._addItem(mn_node, m_node) |
159 if repopulate: |
182 if repopulate: |
160 self.endInsertRows() |
183 self.endInsertRows() |
161 |
184 |
162 self.__populated = True |
185 self.__populated = True |
163 else: |
186 else: |
164 self.clear() |
187 self.clear() |
165 self.__populated = False |
188 self.__populated = False |
166 |
189 |
167 def isPopulated(self): |
190 def isPopulated(self): |
168 """ |
191 """ |
169 Public method to check, if the model is populated. |
192 Public method to check, if the model is populated. |
170 |
193 |
171 @return flag indicating a populated model |
194 @return flag indicating a populated model |
172 @rtype bool |
195 @rtype bool |
173 """ |
196 """ |
174 return self.__populated |
197 return self.__populated |
175 |
198 |
176 def repopulate(self): |
199 def repopulate(self): |
177 """ |
200 """ |
178 Public slot to repopulate the model. |
201 Public slot to repopulate the model. |
179 """ |
202 """ |
180 self.clear() |
203 self.clear() |
181 self.__populateModel(repopulate=True) |
204 self.__populateModel(repopulate=True) |
182 |
205 |
183 def editor(self): |
206 def editor(self): |
184 """ |
207 """ |
185 Public method to retrieve a reference to the editor. |
208 Public method to retrieve a reference to the editor. |
186 |
209 |
187 @return reference to the editor |
210 @return reference to the editor |
188 @rtype Editor |
211 @rtype Editor |
189 """ |
212 """ |
190 return self.__editor |
213 return self.__editor |
191 |
214 |
192 def fileName(self): |
215 def fileName(self): |
193 """ |
216 """ |
194 Public method to retrieve the file name of the editor. |
217 Public method to retrieve the file name of the editor. |
195 |
218 |
196 @return file name of the editor |
219 @return file name of the editor |
197 @rtype str |
220 @rtype str |
198 """ |
221 """ |
199 return self.__filename |
222 return self.__filename |
200 |
223 |
201 def itemIndexByLine(self, lineno): |
224 def itemIndexByLine(self, lineno): |
202 """ |
225 """ |
203 Public method to find an item's index given a line number. |
226 Public method to find an item's index given a line number. |
204 |
227 |
205 @param lineno one based line number of the item |
228 @param lineno one based line number of the item |
206 @type int |
229 @type int |
207 @return index of the item found |
230 @return index of the item found |
208 @rtype QModelIndex |
231 @rtype QModelIndex |
209 """ |
232 """ |
|
233 |
210 def findItem(lineno, parent): |
234 def findItem(lineno, parent): |
211 """ |
235 """ |
212 Function to iteratively search for an item containing the given |
236 Function to iteratively search for an item containing the given |
213 line. |
237 line. |
214 |
238 |
215 @param lineno one based line number of the item |
239 @param lineno one based line number of the item |
216 @type int |
240 @type int |
217 @param parent reference to the parent item |
241 @param parent reference to the parent item |
218 @type BrowserItem |
242 @type BrowserItem |
219 @return found item or None |
243 @return found item or None |