51 super().__init__(parent) |
51 super().__init__(parent) |
52 if projectType: |
52 if projectType: |
53 self.setObjectName("APIs_{0}_{1}".format(language, projectType)) |
53 self.setObjectName("APIs_{0}_{1}".format(language, projectType)) |
54 else: |
54 else: |
55 self.setObjectName("APIs_{0}".format(language)) |
55 self.setObjectName("APIs_{0}".format(language)) |
56 |
56 |
57 self.__inPreparation = False |
57 self.__inPreparation = False |
58 self.__language = language |
58 self.__language = language |
59 self.__projectType = projectType |
59 self.__projectType = projectType |
60 self.__forPreparation = forPreparation |
60 self.__forPreparation = forPreparation |
61 self.__lexer = Lexers.getLexer(self.__language) |
61 self.__lexer = Lexers.getLexer(self.__language) |
62 self.__apifiles = Preferences.getEditorAPI(self.__language, |
62 self.__apifiles = Preferences.getEditorAPI(self.__language, self.__projectType) |
63 self.__projectType) |
|
64 self.__apifiles.sort() |
63 self.__apifiles.sort() |
65 if self.__lexer is None: |
64 if self.__lexer is None: |
66 self.__apis = None |
65 self.__apis = None |
67 else: |
66 else: |
68 self.__apis = QsciAPIs(self.__lexer) |
67 self.__apis = QsciAPIs(self.__lexer) |
69 self.__apis.apiPreparationFinished.connect( |
68 self.__apis.apiPreparationFinished.connect(self.__apiPreparationFinished) |
70 self.__apiPreparationFinished) |
69 self.__apis.apiPreparationCancelled.connect(self.__apiPreparationCancelled) |
71 self.__apis.apiPreparationCancelled.connect( |
70 self.__apis.apiPreparationStarted.connect(self.__apiPreparationStarted) |
72 self.__apiPreparationCancelled) |
|
73 self.__apis.apiPreparationStarted.connect( |
|
74 self.__apiPreparationStarted) |
|
75 self.__loadAPIs() |
71 self.__loadAPIs() |
76 |
72 |
77 def __loadAPIs(self): |
73 def __loadAPIs(self): |
78 """ |
74 """ |
79 Private method to load the APIs. |
75 Private method to load the APIs. |
80 """ |
76 """ |
81 if self.__apis.isPrepared(): |
77 if self.__apis.isPrepared(): |
82 # load a prepared API file |
78 # load a prepared API file |
83 if ( |
79 if not self.__forPreparation and Preferences.getEditor("AutoPrepareAPIs"): |
84 not self.__forPreparation and |
|
85 Preferences.getEditor("AutoPrepareAPIs") |
|
86 ): |
|
87 self.prepareAPIs() |
80 self.prepareAPIs() |
88 self.__apis.loadPrepared(self.__preparedName()) |
81 self.__apis.loadPrepared(self.__preparedName()) |
89 else: |
82 else: |
90 # load the raw files and prepare the API file |
83 # load the raw files and prepare the API file |
91 if ( |
84 if not self.__forPreparation and Preferences.getEditor("AutoPrepareAPIs"): |
92 not self.__forPreparation and |
|
93 Preferences.getEditor("AutoPrepareAPIs") |
|
94 ): |
|
95 self.prepareAPIs(ondemand=True) |
85 self.prepareAPIs(ondemand=True) |
96 |
86 |
97 def reloadAPIs(self): |
87 def reloadAPIs(self): |
98 """ |
88 """ |
99 Public method to reload the API information. |
89 Public method to reload the API information. |
100 """ |
90 """ |
101 if ( |
91 if not self.__forPreparation and Preferences.getEditor("AutoPrepareAPIs"): |
102 not self.__forPreparation and |
|
103 Preferences.getEditor("AutoPrepareAPIs") |
|
104 ): |
|
105 self.prepareAPIs() |
92 self.prepareAPIs() |
106 self.__loadAPIs() |
93 self.__loadAPIs() |
107 |
94 |
108 def getQsciAPIs(self): |
95 def getQsciAPIs(self): |
109 """ |
96 """ |
110 Public method to get a reference to QsciAPIs object. |
97 Public method to get a reference to QsciAPIs object. |
111 |
98 |
112 @return reference to the QsciAPIs object (QsciAPIs) |
99 @return reference to the QsciAPIs object (QsciAPIs) |
113 """ |
100 """ |
114 if ( |
101 if not self.__forPreparation and Preferences.getEditor("AutoPrepareAPIs"): |
115 not self.__forPreparation and |
|
116 Preferences.getEditor("AutoPrepareAPIs") |
|
117 ): |
|
118 self.prepareAPIs() |
102 self.prepareAPIs() |
119 return self.__apis |
103 return self.__apis |
120 |
104 |
121 def isEmpty(self): |
105 def isEmpty(self): |
122 """ |
106 """ |
123 Public method to check, if the object has API files configured. |
107 Public method to check, if the object has API files configured. |
124 |
108 |
125 @return flag indicating no API files have been configured (boolean) |
109 @return flag indicating no API files have been configured (boolean) |
126 """ |
110 """ |
127 return len(self.__apifiles) == 0 |
111 return len(self.__apifiles) == 0 |
128 |
112 |
129 def __apiPreparationFinished(self): |
113 def __apiPreparationFinished(self): |
130 """ |
114 """ |
131 Private method called to save an API, after it has been prepared. |
115 Private method called to save an API, after it has been prepared. |
132 """ |
116 """ |
133 self.__apis.savePrepared(self.__preparedName()) |
117 self.__apis.savePrepared(self.__preparedName()) |
134 self.__inPreparation = False |
118 self.__inPreparation = False |
135 self.apiPreparationFinished.emit() |
119 self.apiPreparationFinished.emit() |
136 |
120 |
137 def __apiPreparationCancelled(self): |
121 def __apiPreparationCancelled(self): |
138 """ |
122 """ |
139 Private method called, after the API preparation process has been |
123 Private method called, after the API preparation process has been |
140 cancelled. |
124 cancelled. |
141 """ |
125 """ |
142 self.__inPreparation = False |
126 self.__inPreparation = False |
143 self.apiPreparationCancelled.emit() |
127 self.apiPreparationCancelled.emit() |
144 |
128 |
145 def __apiPreparationStarted(self): |
129 def __apiPreparationStarted(self): |
146 """ |
130 """ |
147 Private method called, when the API preparation process started. |
131 Private method called, when the API preparation process started. |
148 """ |
132 """ |
149 self.__inPreparation = True |
133 self.__inPreparation = True |
150 self.apiPreparationStarted.emit() |
134 self.apiPreparationStarted.emit() |
151 |
135 |
152 def prepareAPIs(self, ondemand=False, rawList=None): |
136 def prepareAPIs(self, ondemand=False, rawList=None): |
153 """ |
137 """ |
154 Public method to prepare the APIs if necessary. |
138 Public method to prepare the APIs if necessary. |
155 |
139 |
156 @param ondemand flag indicating a requested preparation (boolean) |
140 @param ondemand flag indicating a requested preparation (boolean) |
157 @param rawList list of raw API files (list of strings) |
141 @param rawList list of raw API files (list of strings) |
158 """ |
142 """ |
159 if self.__apis is None or self.__inPreparation: |
143 if self.__apis is None or self.__inPreparation: |
160 return |
144 return |
161 |
145 |
162 needsPreparation = False |
146 needsPreparation = False |
163 if ondemand: |
147 if ondemand: |
164 needsPreparation = True |
148 needsPreparation = True |
165 else: |
149 else: |
166 # check, if a new preparation is necessary |
150 # check, if a new preparation is necessary |
169 preparedPath = pathlib.Path(preparedAPIs) |
153 preparedPath = pathlib.Path(preparedAPIs) |
170 if not preparedPath.exists(): |
154 if not preparedPath.exists(): |
171 needsPreparation = True |
155 needsPreparation = True |
172 else: |
156 else: |
173 preparedAPIsModified = preparedPath.stat().st_mtime |
157 preparedAPIsModified = preparedPath.stat().st_mtime |
174 apifiles = sorted(Preferences.getEditorAPI( |
158 apifiles = sorted( |
175 self.__language, self.__projectType)) |
159 Preferences.getEditorAPI(self.__language, self.__projectType) |
|
160 ) |
176 if self.__apifiles != apifiles: |
161 if self.__apifiles != apifiles: |
177 needsPreparation = True |
162 needsPreparation = True |
178 for apifile in apifiles: |
163 for apifile in apifiles: |
179 apifilePath = pathlib.Path(apifile) |
164 apifilePath = pathlib.Path(apifile) |
180 if ( |
165 if ( |
181 apifilePath.exists() and |
166 apifilePath.exists() |
182 apifilePath.stat().st_mtime > |
167 and apifilePath.stat().st_mtime > preparedAPIsModified |
183 preparedAPIsModified |
|
184 ): |
168 ): |
185 needsPreparation = True |
169 needsPreparation = True |
186 break |
170 break |
187 |
171 |
188 if needsPreparation: |
172 if needsPreparation: |
189 # do the preparation |
173 # do the preparation |
190 self.__apis.clear() |
174 self.__apis.clear() |
191 if rawList: |
175 if rawList: |
192 apifiles = rawList |
176 apifiles = rawList |
193 else: |
177 else: |
194 apifiles = Preferences.getEditorAPI( |
178 apifiles = Preferences.getEditorAPI(self.__language, self.__projectType) |
195 self.__language, self.__projectType) |
|
196 for apifile in apifiles: |
179 for apifile in apifiles: |
197 self.__apis.load(apifile) |
180 self.__apis.load(apifile) |
198 self.__apis.prepare() |
181 self.__apis.prepare() |
199 self.__apifiles = apifiles |
182 self.__apifiles = apifiles |
200 |
183 |
201 def cancelPreparation(self): |
184 def cancelPreparation(self): |
202 """ |
185 """ |
203 Public slot to cancel the APIs preparation. |
186 Public slot to cancel the APIs preparation. |
204 """ |
187 """ |
205 self.__apis and self.__apis.cancelPreparation() |
188 self.__apis and self.__apis.cancelPreparation() |
206 |
189 |
207 def installedAPIFiles(self): |
190 def installedAPIFiles(self): |
208 """ |
191 """ |
209 Public method to get a list of installed API files. |
192 Public method to get a list of installed API files. |
210 |
193 |
211 @return list of installed API files (list of strings) |
194 @return list of installed API files (list of strings) |
212 """ |
195 """ |
213 if self.__apis is not None: |
196 if self.__apis is not None: |
214 if Globals.isWindowsPlatform(): |
197 if Globals.isWindowsPlatform(): |
215 qsciPath = os.path.join( |
198 qsciPath = os.path.join(Globals.getPyQt6ModulesDirectory(), "qsci") |
216 Globals.getPyQt6ModulesDirectory(), "qsci") |
|
217 if os.path.exists(qsciPath): |
199 if os.path.exists(qsciPath): |
218 # it's the installer |
200 # it's the installer |
219 if self.__lexer.lexerName() is not None: |
201 if self.__lexer.lexerName() is not None: |
220 apidir = os.path.join(qsciPath, "api", |
202 apidir = os.path.join(qsciPath, "api", self.__lexer.lexerName()) |
221 self.__lexer.lexerName()) |
|
222 fnames = [] |
203 fnames = [] |
223 filist = QDir(apidir).entryInfoList( |
204 filist = QDir(apidir).entryInfoList( |
224 ["*.api"], QDir.Filter.Files, |
205 ["*.api"], QDir.Filter.Files, QDir.SortFlag.IgnoreCase |
225 QDir.SortFlag.IgnoreCase) |
206 ) |
226 for fi in filist: |
207 for fi in filist: |
227 fnames.append(fi.absoluteFilePath()) |
208 fnames.append(fi.absoluteFilePath()) |
228 return fnames |
209 return fnames |
229 else: |
210 else: |
230 return [] |
211 return [] |
231 |
212 |
232 return self.__apis.installedAPIFiles() |
213 return self.__apis.installedAPIFiles() |
233 else: |
214 else: |
234 return [] |
215 return [] |
235 |
216 |
236 def __preparedName(self): |
217 def __preparedName(self): |
237 """ |
218 """ |
238 Private method returning the default name of a prepared API file. |
219 Private method returning the default name of a prepared API file. |
239 |
220 |
240 @return complete filename for the Prepared APIs file (string) |
221 @return complete filename for the Prepared APIs file (string) |
241 """ |
222 """ |
242 apisDir = os.path.join(Globals.getConfigDir(), "APIs") |
223 apisDir = os.path.join(Globals.getConfigDir(), "APIs") |
243 if self.__apis is not None: |
224 if self.__apis is not None: |
244 if self.__projectType: |
225 if self.__projectType: |
245 filename = "{0}_{1}.pap".format(self.__language, |
226 filename = "{0}_{1}.pap".format(self.__language, self.__projectType) |
246 self.__projectType) |
|
247 else: |
227 else: |
248 filename = "{0}.pap".format(self.__language) |
228 filename = "{0}.pap".format(self.__language) |
249 return os.path.join(apisDir, filename) |
229 return os.path.join(apisDir, filename) |
250 else: |
230 else: |
251 return "" |
231 return "" |
252 |
232 |
253 |
233 |
254 class APIsManager(QObject): |
234 class APIsManager(QObject): |
255 """ |
235 """ |
256 Class implementing the APIsManager class, which is the central store for |
236 Class implementing the APIsManager class, which is the central store for |
257 API information used by autocompletion and calltips. |
237 API information used by autocompletion and calltips. |
258 """ |
238 """ |
|
239 |
259 def __init__(self, parent=None): |
240 def __init__(self, parent=None): |
260 """ |
241 """ |
261 Constructor |
242 Constructor |
262 |
243 |
263 @param parent reference to the parent object (QObject) |
244 @param parent reference to the parent object (QObject) |
264 """ |
245 """ |
265 super().__init__(parent) |
246 super().__init__(parent) |
266 self.setObjectName("APIsManager") |
247 self.setObjectName("APIsManager") |
267 |
248 |
268 self.__apis = {} |
249 self.__apis = {} |
269 |
250 |
270 def reloadAPIs(self): |
251 def reloadAPIs(self): |
271 """ |
252 """ |
272 Public slot to reload the api information. |
253 Public slot to reload the api information. |
273 """ |
254 """ |
274 for api in list(self.__apis.values()): |
255 for api in list(self.__apis.values()): |
275 api and api.reloadAPIs() |
256 api and api.reloadAPIs() |
276 |
257 |
277 def getAPIs(self, language, projectType="", forPreparation=False): |
258 def getAPIs(self, language, projectType="", forPreparation=False): |
278 """ |
259 """ |
279 Public method to get an APIs object for autocompletion/calltips. |
260 Public method to get an APIs object for autocompletion/calltips. |
280 |
261 |
281 This method creates and loads an APIs object dynamically upon request. |
262 This method creates and loads an APIs object dynamically upon request. |
282 This saves memory for languages, that might not be needed at the |
263 This saves memory for languages, that might not be needed at the |
283 moment. |
264 moment. |
284 |
265 |
285 @param language language of the requested APIs object |
266 @param language language of the requested APIs object |
286 @type str |
267 @type str |
287 @param projectType type of the project |
268 @param projectType type of the project |
288 @type str |
269 @type str |
289 @param forPreparation flag indicating the requested APIs object is just |
270 @param forPreparation flag indicating the requested APIs object is just |