src/eric7/Preferences/ConfigurationPages/EditorAPIsPage.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 9185
8975ed45c22d
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2006 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the Editor APIs configuration page.
8 """
9
10 import contextlib
11 import pathlib
12
13 from PyQt6.QtCore import pyqtSlot
14 from PyQt6.QtWidgets import QDialog
15
16 from EricWidgets.EricApplication import ericApp
17 from EricWidgets import EricMessageBox
18 from EricWidgets.EricListSelectionDialog import EricListSelectionDialog
19 from EricWidgets.EricPathPicker import EricPathPickerModes
20
21 from .ConfigurationPageBase import ConfigurationPageBase
22 from .Ui_EditorAPIsPage import Ui_EditorAPIsPage
23
24 import Preferences
25 import Utilities
26
27
28 class EditorAPIsPage(ConfigurationPageBase, Ui_EditorAPIsPage):
29 """
30 Class implementing the Editor APIs configuration page.
31 """
32 def __init__(self):
33 """
34 Constructor
35 """
36 super().__init__()
37 self.setupUi(self)
38 self.setObjectName("EditorAPIsPage")
39
40 self.apiFilePicker.setMode(EricPathPickerModes.OPEN_FILE_MODE)
41 self.apiFilePicker.setToolTip(self.tr(
42 "Press to select an API file via a selection dialog"))
43 self.apiFilePicker.setFilters(self.tr(
44 "API File (*.api);;All Files (*)"))
45
46 self.prepareApiButton.setText(self.tr("Compile APIs"))
47 self.__currentAPI = None
48 self.__inPreparation = False
49
50 # set initial values
51 self.pluginManager = ericApp().getObject("PluginManager")
52 self.apiAutoPrepareCheckBox.setChecked(
53 Preferences.getEditor("AutoPrepareAPIs"))
54
55 import QScintilla.Lexers
56 self.apis = {}
57 apiLanguages = sorted(
58 [''] + list(QScintilla.Lexers.getSupportedApiLanguages()))
59 for lang in apiLanguages:
60 self.apiLanguageComboBox.addItem(
61 QScintilla.Lexers.getLanguageIcon(lang, False),
62 lang)
63 self.__currentApiLanguage = ""
64 self.on_apiLanguageComboBox_activated(0)
65
66 def __apiKey(self, language, projectType):
67 """
68 Private method to generate a key for the apis dictionary.
69
70 @param language programming language of the API
71 @type str
72 @param projectType project type of the API
73 @type str
74 @return key to be used
75 @rtype str
76 """
77 key = (language, projectType) if projectType else (language, "")
78 return key
79
80 def save(self):
81 """
82 Public slot to save the Editor APIs configuration.
83 """
84 Preferences.setEditor(
85 "AutoPrepareAPIs",
86 self.apiAutoPrepareCheckBox.isChecked())
87
88 language = self.apiLanguageComboBox.currentText()
89 projectType = self.projectTypeComboBox.itemData(
90 self.projectTypeComboBox.currentIndex())
91 key = self.__apiKey(language, projectType)
92 self.apis[key] = self.__editorGetApisFromApiList()
93
94 for (language, projectType), apis in self.apis.items():
95 Preferences.setEditorAPI(language, projectType, apis)
96
97 @pyqtSlot(int)
98 def on_projectTypeComboBox_activated(self, index):
99 """
100 Private slot to handle the selection of a project type.
101
102 @param index index of the selected entry
103 @type str
104 """
105 if self.__currentApiProjectTypeIndex == index:
106 return
107
108 self.__currentApiProjectTypeIndex = index
109 self.__fillApisList()
110
111 @pyqtSlot(int)
112 def on_apiLanguageComboBox_activated(self, index):
113 """
114 Private slot to fill the api listbox of the api page.
115
116 @param index index of the selected entry
117 @type int
118 """
119 language = self.apiLanguageComboBox.itemText(index)
120
121 if self.__currentApiLanguage == language:
122 return
123
124 self.__fillProjectTypeComboBox(language)
125
126 def __fillProjectTypeComboBox(self, language):
127 """
128 Private slot to fill the selection of available project types for the
129 given language.
130
131 @param language selected API language
132 @type str
133 """
134 self.projectTypeComboBox.clear()
135
136 apiProjectTypes = [("", "")]
137 with contextlib.suppress(KeyError):
138 apiProjectTypes += sorted(
139 (trans, ptype) for ptype, trans in
140 ericApp().getObject("Project").getProjectTypes(language).items()
141 )
142 for projectTypeStr, projectType in apiProjectTypes:
143 self.projectTypeComboBox.addItem(projectTypeStr, projectType)
144
145 self.__currentApiProjectTypeIndex = -1
146 self.__currentApiProjectType = ""
147
148 self.on_projectTypeComboBox_activated(0)
149
150 def __fillApisList(self):
151 """
152 Private slot to fill the list of API files.
153 """
154 self.apis[
155 self.__apiKey(self.__currentApiLanguage,
156 self.__currentApiProjectType)
157 ] = self.__editorGetApisFromApiList()
158
159 self.__currentApiLanguage = self.apiLanguageComboBox.currentText()
160 self.__currentApiProjectType = self.projectTypeComboBox.itemData(
161 self.projectTypeComboBox.currentIndex())
162 self.apiList.clear()
163
164 if not self.__currentApiLanguage:
165 self.apiGroup.setEnabled(False)
166 return
167
168 self.apiGroup.setEnabled(True)
169 self.deleteApiFileButton.setEnabled(False)
170 self.addApiFileButton.setEnabled(False)
171 self.apiFilePicker.clear()
172
173 key = self.__apiKey(self.__currentApiLanguage,
174 self.__currentApiProjectType)
175 if key not in self.apis:
176 # populate on demand
177 self.apis[key] = Preferences.getEditorAPI(
178 self.__currentApiLanguage,
179 projectType=self.__currentApiProjectType)[:]
180 for api in self.apis[key]:
181 if api:
182 self.apiList.addItem(api)
183 self.prepareApiButton.setEnabled(self.apiList.count() > 0)
184
185 from QScintilla.APIsManager import APIsManager
186 self.__currentAPI = APIsManager().getAPIs(
187 self.__currentApiLanguage,
188 projectType=self.__currentApiProjectType)
189 if self.__currentAPI is not None:
190 self.__currentAPI.apiPreparationFinished.connect(
191 self.__apiPreparationFinished)
192 self.__currentAPI.apiPreparationCancelled.connect(
193 self.__apiPreparationCancelled)
194 self.__currentAPI.apiPreparationStarted.connect(
195 self.__apiPreparationStarted)
196 self.addInstalledApiFileButton.setEnabled(
197 len(self.__currentAPI.installedAPIFiles()) > 0)
198 else:
199 self.addInstalledApiFileButton.setEnabled(False)
200
201 self.addPluginApiFileButton.setEnabled(
202 len(self.pluginManager.getPluginApiFiles(
203 self.__currentApiLanguage)) > 0)
204
205 def __editorGetApisFromApiList(self):
206 """
207 Private slot to retrieve the api filenames from the list.
208
209 @return list of api filenames (list of strings)
210 """
211 apis = []
212 for row in range(self.apiList.count()):
213 apis.append(self.apiList.item(row).text())
214 return apis
215
216 @pyqtSlot()
217 def on_addApiFileButton_clicked(self):
218 """
219 Private slot to add the api file displayed to the listbox.
220 """
221 file = self.apiFilePicker.text()
222 if file:
223 self.apiList.addItem(Utilities.toNativeSeparators(file))
224 self.apiFilePicker.clear()
225 self.prepareApiButton.setEnabled(self.apiList.count() > 0)
226
227 @pyqtSlot()
228 def on_deleteApiFileButton_clicked(self):
229 """
230 Private slot to delete the currently selected file of the listbox.
231 """
232 crow = self.apiList.currentRow()
233 if crow >= 0:
234 itm = self.apiList.takeItem(crow) # __IGNORE_WARNING__
235 del itm
236 self.prepareApiButton.setEnabled(self.apiList.count() > 0)
237
238 @pyqtSlot()
239 def on_addInstalledApiFileButton_clicked(self):
240 """
241 Private slot to add an API file from the list of installed API files
242 for the selected lexer language.
243 """
244 installedAPIFiles = self.__currentAPI.installedAPIFiles()
245 if installedAPIFiles:
246 installedAPIFilesPath = pathlib.Path(installedAPIFiles[0]).parent
247 installedAPIFilesShort = [
248 pathlib.Path(f).name for f in installedAPIFiles
249 ]
250 dlg = EricListSelectionDialog(
251 sorted(installedAPIFilesShort),
252 title=self.tr("Add from installed APIs"),
253 message=self.tr("Select from the list of installed API files"),
254 checkBoxSelection=True,
255 parent=self
256 )
257 if dlg.exec() == QDialog.DialogCode.Accepted:
258 self.apiList.addItems([
259 str(installedAPIFilesPath / s) for s in dlg.getSelection()
260 ])
261 else:
262 EricMessageBox.warning(
263 self,
264 self.tr("Add from installed APIs"),
265 self.tr("""There are no APIs installed yet."""
266 """ Selection is not available."""))
267 self.addInstalledApiFileButton.setEnabled(False)
268 self.prepareApiButton.setEnabled(self.apiList.count() > 0)
269
270 @pyqtSlot()
271 def on_addPluginApiFileButton_clicked(self):
272 """
273 Private slot to add an API file from the list of API files installed
274 by plugins for the selected lexer language.
275 """
276 pluginAPIFiles = self.pluginManager.getPluginApiFiles(
277 self.__currentApiLanguage)
278 pluginAPIFilesDict = {
279 pathlib.Path(f).name: pathlib.Path(f) for f in pluginAPIFiles
280 }
281 dlg = EricListSelectionDialog(
282 sorted(pluginAPIFilesDict.keys()),
283 title=self.tr("Add from Plugin APIs"),
284 message=self.tr(
285 "Select from the list of API files installed by plugins"),
286 checkBoxSelection=True,
287 parent=self
288 )
289 if dlg.exec() == QDialog.DialogCode.Accepted:
290 self.apiList.addItems([
291 str(pluginAPIFilesDict[s]) for s in dlg.getSelection()
292 ])
293 self.prepareApiButton.setEnabled(self.apiList.count() > 0)
294
295 @pyqtSlot()
296 def on_prepareApiButton_clicked(self):
297 """
298 Private slot to prepare the API file for the currently selected
299 language.
300 """
301 if self.__inPreparation:
302 self.__currentAPI and self.__currentAPI.cancelPreparation()
303 else:
304 if self.__currentAPI is not None:
305 self.__currentAPI.prepareAPIs(
306 ondemand=True,
307 rawList=self.__editorGetApisFromApiList())
308
309 def __apiPreparationFinished(self):
310 """
311 Private method called after the API preparation has finished.
312 """
313 self.prepareApiProgressBar.reset()
314 self.prepareApiProgressBar.setRange(0, 100)
315 self.prepareApiProgressBar.setValue(0)
316 self.prepareApiButton.setText(self.tr("Compile APIs"))
317 self.__inPreparation = False
318
319 def __apiPreparationCancelled(self):
320 """
321 Private slot called after the API preparation has been cancelled.
322 """
323 self.__apiPreparationFinished()
324
325 def __apiPreparationStarted(self):
326 """
327 Private method called after the API preparation has started.
328 """
329 self.prepareApiProgressBar.setRange(0, 0)
330 self.prepareApiProgressBar.setValue(0)
331 self.prepareApiButton.setText(self.tr("Cancel compilation"))
332 self.__inPreparation = True
333
334 def saveState(self):
335 """
336 Public method to save the current state of the widget.
337
338 @return tuple containing the index of the selected lexer language
339 and the index of the selected project type
340 @rtype tuple of int and int
341 """
342 return (
343 self.apiLanguageComboBox.currentIndex(),
344 self.projectTypeComboBox.currentIndex()
345 )
346
347 def setState(self, state):
348 """
349 Public method to set the state of the widget.
350
351 @param state state data generated by saveState
352 """
353 self.apiLanguageComboBox.setCurrentIndex(state[0])
354 self.on_apiLanguageComboBox_activated(
355 self.apiLanguageComboBox.currentIndex())
356
357 self.projectTypeComboBox.setCurrentIndex(state[1])
358 self.on_projectTypeComboBox_activated(state[1])
359
360 @pyqtSlot()
361 def on_apiList_itemSelectionChanged(self):
362 """
363 Private slot to react on changes of API selections.
364 """
365 self.deleteApiFileButton.setEnabled(
366 len(self.apiList.selectedItems()) > 0)
367
368 @pyqtSlot(str)
369 def on_apiFilePicker_textChanged(self, txt):
370 """
371 Private slot to handle the entering of an API file name.
372
373 @param txt text of the line edit (string)
374 """
375 enable = txt != ""
376
377 if enable:
378 # check for already added file
379 for row in range(self.apiList.count()):
380 if txt == self.apiList.item(row).text():
381 enable = False
382 break
383
384 self.addApiFileButton.setEnabled(enable)
385
386
387 def create(dlg):
388 """
389 Module function to create the configuration page.
390
391 @param dlg reference to the configuration dialog
392 @return reference to the instantiated page (ConfigurationPageBase)
393 """
394 page = EditorAPIsPage()
395 return page

eric ide

mercurial