src/eric7/QScintilla/APIsManager.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9361
718bc86e1c3f
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
19 19
20 20
21 class APIs(QObject): 21 class APIs(QObject):
22 """ 22 """
23 Class implementing an API storage entity. 23 Class implementing an API storage entity.
24 24
25 @signal apiPreparationFinished() emitted after the API preparation has 25 @signal apiPreparationFinished() emitted after the API preparation has
26 finished 26 finished
27 @signal apiPreparationCancelled() emitted after the API preparation has 27 @signal apiPreparationCancelled() emitted after the API preparation has
28 been cancelled 28 been cancelled
29 @signal apiPreparationStarted() emitted after the API preparation has 29 @signal apiPreparationStarted() emitted after the API preparation has
30 started 30 started
31 """ 31 """
32
32 apiPreparationFinished = pyqtSignal() 33 apiPreparationFinished = pyqtSignal()
33 apiPreparationCancelled = pyqtSignal() 34 apiPreparationCancelled = pyqtSignal()
34 apiPreparationStarted = pyqtSignal() 35 apiPreparationStarted = pyqtSignal()
35 36
36 def __init__(self, language, projectType="", forPreparation=False, 37 def __init__(self, language, projectType="", forPreparation=False, parent=None):
37 parent=None):
38 """ 38 """
39 Constructor 39 Constructor
40 40
41 @param language language of the APIs object 41 @param language language of the APIs object
42 @type str 42 @type str
43 @param projectType type of the project 43 @param projectType type of the project
44 @type str 44 @type str
45 @param forPreparation flag indicating this object is just needed 45 @param forPreparation flag indicating this object is just needed
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
291 @type bool 272 @type bool
292 @return reference to the APIs object 273 @return reference to the APIs object
293 @rtype APIs 274 @rtype APIs
294 """ 275 """
295 if forPreparation: 276 if forPreparation:
296 return APIs(language, projectType=projectType, 277 return APIs(
297 forPreparation=forPreparation) 278 language, projectType=projectType, forPreparation=forPreparation
279 )
298 else: 280 else:
299 try: 281 try:
300 return self.__apis[(language, projectType)] 282 return self.__apis[(language, projectType)]
301 except KeyError: 283 except KeyError:
302 if language in Lexers.getSupportedApiLanguages(): 284 if language in Lexers.getSupportedApiLanguages():
303 # create the api object 285 # create the api object
304 self.__apis[(language, projectType)] = APIs( 286 self.__apis[(language, projectType)] = APIs(
305 language, projectType=projectType) 287 language, projectType=projectType
288 )
306 return self.__apis[(language, projectType)] 289 return self.__apis[(language, projectType)]
307 else: 290 else:
308 return None 291 return None

eric ide

mercurial