Skip to content

Commit 3b4dfd7

Browse files
committed
[FEATURE] [pyqgis-console] Module to generate prepared APIs for calltips and auto-completion
1 parent 3115c30 commit 3b4dfd7

7 files changed

+376
-92
lines changed

python/console/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ SET(PY_CONSOLE_FILES
77
console_settings.py
88
console_output.py
99
console_editor.py
10+
console_compile_apis.py
1011
__init__.py
1112
)
1213

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# -*- coding:utf-8 -*-
2+
"""
3+
/***************************************************************************
4+
Module to generate prepared APIs for calltips and auto-completion.
5+
-------------------
6+
begin : 2012-09-10
7+
copyright : (C) 2012 Larry Shaffer
8+
email : larrys (at) dakotacarto (dot) com
9+
***************************************************************************/
10+
11+
/***************************************************************************
12+
* *
13+
* This program is free software; you can redistribute it and/or modify *
14+
* it under the terms of the GNU General Public License as published by *
15+
* the Free Software Foundation; either version 2 of the License, or *
16+
* (at your option) any later version. *
17+
* *
18+
***************************************************************************/
19+
Portions of this file contain code from Eric4 APIsManager module.
20+
"""
21+
22+
import sys
23+
import os
24+
import shutil
25+
import fnmatch
26+
import glob
27+
28+
from PyQt4.Qsci import *
29+
from PyQt4.QtGui import *
30+
from PyQt4.QtCore import *
31+
32+
from ui_console_compile_apis import Ui_APIsDialogPythonConsole
33+
34+
class PrepareAPIDialog(QDialog):
35+
def __init__(self, api_lexer, api_files, pap_file, parent=None):
36+
QDialog.__init__(self, parent)
37+
self.ui = Ui_APIsDialogPythonConsole()
38+
self.ui.setupUi(self)
39+
self.setWindowTitle(QCoreApplication.translate("PythonConsole","Compile APIs"))
40+
self.ui.plainTextEdit.setVisible(False)
41+
self.ui.textEdit_Qsci.setVisible(False)
42+
self.adjustSize()
43+
self._api = None
44+
self.ui.buttonBox.rejected.connect(self._stopPreparation)
45+
self._api_files = api_files
46+
self._api_lexer = api_lexer
47+
self._pap_file = pap_file
48+
49+
def _clearLexer(self):
50+
# self.ui.textEdit_Qsci.setLexer(0)
51+
self.qlexer = None
52+
53+
def _stopPreparation(self):
54+
if self._api is not None:
55+
self._api.cancelPreparation()
56+
self._api = None
57+
self._clearLexer()
58+
self.close()
59+
60+
def _preparationFinished(self):
61+
self._clearLexer()
62+
if os.path.exists(self._pap_file):
63+
os.remove(self._pap_file)
64+
self.ui.label.setText(QCoreApplication.translate("PythonConsole","Saving prepared file..."))
65+
prepd = self._api.savePrepared(unicode(self._pap_file))
66+
rslt = self.trUtf8("Error")
67+
if prepd:
68+
rslt = QCoreApplication.translate("PythonConsole","Saved")
69+
self.ui.label.setText('{0} {1}'.format(self.ui.label.text(), rslt))
70+
self._api = None
71+
self.ui.progressBar.setVisible(False)
72+
self.ui.buttonBox.button(QDialogButtonBox.Cancel).setText(
73+
QCoreApplication.translate("PythonConsole","Done"))
74+
self.adjustSize()
75+
76+
def prepareAPI(self):
77+
# self.ui.textEdit_Qsci.setLexer(0)
78+
exec 'self.qlexer = {0}(self.ui.textEdit_Qsci)'.format(self._api_lexer)
79+
# self.ui.textEdit_Qsci.setLexer(self.qlexer)
80+
self._api = QsciAPIs(self.qlexer)
81+
self._api.apiPreparationFinished.connect(self._preparationFinished)
82+
for api_file in self._api_files:
83+
self._api.load(unicode(api_file))
84+
try:
85+
self._api.prepare()
86+
except Exception, err:
87+
self._api = None
88+
self._clearLexer()
89+
self.ui.label.setText(QCoreApplication.translate("PythonConsole","Error preparing file..."))
90+
self.ui.progressBar.setVisible(False)
91+
self.ui.plainTextEdit.setVisible(True)
92+
self.ui.plainTextEdit.insertPlainText(err)
93+
self.ui.buttonBox.button(QDialogButtonBox.Cancel).setText(
94+
self.trUtf8("Done"))
95+
self.adjustSize()
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>APIsDialogPythonConsole</class>
4+
<widget class="QDialog" name="APIsDialogPythonConsole">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>320</width>
10+
<height>280</height>
11+
</rect>
12+
</property>
13+
<property name="minimumSize">
14+
<size>
15+
<width>320</width>
16+
<height>0</height>
17+
</size>
18+
</property>
19+
<property name="windowTitle">
20+
<string/>
21+
</property>
22+
<layout class="QVBoxLayout" name="verticalLayout">
23+
<item>
24+
<widget class="QLabel" name="label">
25+
<property name="minimumSize">
26+
<size>
27+
<width>320</width>
28+
<height>0</height>
29+
</size>
30+
</property>
31+
<property name="text">
32+
<string>Generating prepared API file (please wait)...</string>
33+
</property>
34+
</widget>
35+
</item>
36+
<item>
37+
<widget class="QProgressBar" name="progressBar">
38+
<property name="enabled">
39+
<bool>true</bool>
40+
</property>
41+
<property name="maximum">
42+
<number>0</number>
43+
</property>
44+
<property name="value">
45+
<number>-1</number>
46+
</property>
47+
</widget>
48+
</item>
49+
<item>
50+
<widget class="QPlainTextEdit" name="plainTextEdit">
51+
<property name="font">
52+
<font>
53+
<pointsize>12</pointsize>
54+
</font>
55+
</property>
56+
<property name="readOnly">
57+
<bool>true</bool>
58+
</property>
59+
</widget>
60+
</item>
61+
<item>
62+
<widget class="QsciScintilla" name="textEdit_Qsci">
63+
<property name="toolTip">
64+
<string/>
65+
</property>
66+
<property name="whatsThis">
67+
<string/>
68+
</property>
69+
<property name="verticalScrollBarPolicy">
70+
<enum>Qt::ScrollBarAlwaysOff</enum>
71+
</property>
72+
<property name="horizontalScrollBarPolicy">
73+
<enum>Qt::ScrollBarAlwaysOff</enum>
74+
</property>
75+
</widget>
76+
</item>
77+
<item>
78+
<widget class="QDialogButtonBox" name="buttonBox">
79+
<property name="orientation">
80+
<enum>Qt::Horizontal</enum>
81+
</property>
82+
<property name="standardButtons">
83+
<set>QDialogButtonBox::Cancel</set>
84+
</property>
85+
</widget>
86+
</item>
87+
</layout>
88+
</widget>
89+
<customwidgets>
90+
<customwidget>
91+
<class>QsciScintilla</class>
92+
<extends>QFrame</extends>
93+
<header>Qsci/qsciscintilla.h</header>
94+
</customwidget>
95+
</customwidgets>
96+
<resources/>
97+
<connections/>
98+
</ui>

python/console/console_editor.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,11 @@ def setLexers(self):
237237

238238
self.api = QsciAPIs(self.lexer)
239239
chekBoxAPI = self.settings.value("pythonConsole/preloadAPI", True, type=bool)
240+
chekBoxPreparedAPI = self.settings.value("pythonConsole/usePreparedAPIFile", False, type=bool)
240241
if chekBoxAPI:
241-
self.api.loadPrepared( QgsApplication.pkgDataPath() + "/python/qsci_apis/pyqgis_master.pap" )
242+
self.api.loadPrepared(QgsApplication.pkgDataPath() + "/python/qsci_apis/pyqgis_master.pap")
243+
elif chekBoxPreparedAPI:
244+
self.api.loadPrepared(self.settings.value("pythonConsole/preparedAPIFile"))
242245
else:
243246
apiPath = self.settings.value("pythonConsole/userAPI")
244247
for i in range(0, len(apiPath)):

python/console/console_sci.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,11 @@ def setLexers(self):
189189

190190
self.api = QsciAPIs(self.lexer)
191191
chekBoxAPI = self.settings.value("pythonConsole/preloadAPI", True, type=bool)
192+
chekBoxPreparedAPI = self.settings.value("pythonConsole/usePreparedAPIFile", False, type=bool)
192193
if chekBoxAPI:
193-
self.api.loadPrepared( QgsApplication.pkgDataPath() + "/python/qsci_apis/pyqgis_master.pap" )
194+
self.api.loadPrepared(QgsApplication.pkgDataPath() + "/python/qsci_apis/pyqgis_master.pap")
195+
elif chekBoxPreparedAPI:
196+
self.api.loadPrepared(self.settings.value("pythonConsole/preparedAPIFile"))
194197
else:
195198
apiPath = self.settings.value("pythonConsole/userAPI")
196199
for i in range(0, len(apiPath)):

python/console/console_settings.py

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
from PyQt4.QtCore import *
2323
from PyQt4.QtGui import *
24+
from console_compile_apis import PrepareAPIDialog
2425

2526
from ui_console_settings import Ui_SettingsDialogPythonConsole
2627

@@ -32,6 +33,7 @@ def __init__(self, parent):
3233
self.setupUi(self)
3334

3435
self.listPath = []
36+
self.lineEdit.setReadOnly(True)
3537

3638
self.restoreSettings()
3739
self.initialCheck()
@@ -47,6 +49,7 @@ def __init__(self, parent):
4749
SIGNAL("clicked()"), self.loadAPIFile)
4850
self.connect(self.removeAPIpath,
4951
SIGNAL("clicked()"), self.removeAPI)
52+
self.compileAPIs.clicked.connect(self._prepareAPI)
5053

5154
def initialCheck(self):
5255
if self.preloadAPI.isChecked():
@@ -58,6 +61,7 @@ def enableDisable(self, value):
5861
self.tableWidget.setEnabled(value)
5962
self.addAPIpath.setEnabled(value)
6063
self.removeAPIpath.setEnabled(value)
64+
self.groupBoxPreparedAPI.setEnabled(value)
6165

6266
def loadAPIFile(self):
6367
settings = QSettings()
@@ -70,12 +74,41 @@ def loadAPIFile(self):
7074
lastDirPath = QFileInfo(fileAPI).path()
7175
settings.setValue("pythonConsole/lastDirAPIPath", fileAPI)
7276

77+
def _prepareAPI(self):
78+
if self.tableWidget.rowCount() != 0:
79+
pap_file = QFileDialog().getSaveFileName(self,
80+
"",
81+
'*.pap',
82+
"Prepared APIs file (*.pap)")
83+
else:
84+
QMessageBox.information(self, self.tr("Warning!"),
85+
self.tr('You need to add some APIs file in order to compile'))
86+
return
87+
if pap_file:
88+
api_lexer = 'QsciLexerPython'
89+
api_files = []
90+
count = self.tableWidget.rowCount()
91+
for i in range(0, count):
92+
api_files.append(self.tableWidget.item(i, 1).text())
93+
api_dlg = PrepareAPIDialog(api_lexer, api_files, pap_file, self)
94+
api_dlg.show()
95+
api_dlg.activateWindow()
96+
api_dlg.raise_()
97+
api_dlg.prepareAPI()
98+
self.lineEdit.setText(pap_file)
99+
73100
def accept(self):
74-
if not self.preloadAPI.isChecked():
101+
if not self.preloadAPI.isChecked() and \
102+
not self.groupBoxPreparedAPI.isChecked():
75103
if self.tableWidget.rowCount() == 0:
76104
QMessageBox.information(self, self.tr("Warning!"),
77-
self.tr('Please specify API file or check "Use preloaded API files"'))
105+
self.tr('Please specify API file or check "Use preloaded API files"'))
78106
return
107+
if self.groupBoxPreparedAPI.isChecked() and \
108+
not self.lineEdit.text():
109+
QMessageBox.information(self, self.tr("Warning!"),
110+
self.tr('The APIs file was not compiled, click on "Compile APIs..."'))
111+
return
79112
self.saveSettings()
80113
self.listPath = []
81114
QDialog.accept( self )
@@ -122,6 +155,9 @@ def saveSettings(self):
122155
settings.setValue("pythonConsole/autoCompleteEnabledEditor", self.groupBoxAutoCompletionEditor.isChecked())
123156
settings.setValue("pythonConsole/autoCompleteEnabled", self.groupBoxAutoCompletion.isChecked())
124157

158+
settings.setValue("pythonConsole/usePreparedAPIFile", self.groupBoxPreparedAPI.isChecked())
159+
settings.setValue("pythonConsole/preparedAPIFile", self.lineEdit.text())
160+
125161
if self.autoCompFromAPIEditor.isChecked():
126162
settings.setValue("pythonConsole/autoCompleteSourceEditor", 'fromAPI')
127163
elif self.autoCompFromDocEditor.isChecked():
@@ -147,8 +183,9 @@ def restoreSettings(self):
147183
self.fontComboBox.setCurrentFont(QFont(settings.value("pythonConsole/fontfamilytext",
148184
"Monospace")))
149185
self.fontComboBoxEditor.setCurrentFont(QFont(settings.value("pythonConsole/fontfamilytextEditor",
150-
"Monospace")))
186+
"Monospace")))
151187
self.preloadAPI.setChecked(settings.value("pythonConsole/preloadAPI", True, type=bool))
188+
self.lineEdit.setText(settings.value("pythonConsole/preparedAPIFile"))
152189
itemTable = settings.value("pythonConsole/userAPI", [])
153190
if itemTable:
154191
for i in range(len(itemTable)):

0 commit comments

Comments
 (0)