|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2006 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the Debugger General configuration page. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals |
|
11 |
|
12 import socket |
|
13 |
|
14 from PyQt5.QtCore import QRegExp, pyqtSlot |
|
15 from PyQt5.QtWidgets import QLineEdit, QInputDialog |
|
16 from PyQt5.QtNetwork import QNetworkInterface, QAbstractSocket, QHostAddress |
|
17 |
|
18 from E5Gui.E5Application import e5App |
|
19 from E5Gui.E5Completers import E5FileCompleter, E5DirCompleter |
|
20 from E5Gui import E5MessageBox |
|
21 |
|
22 from .ConfigurationPageBase import ConfigurationPageBase |
|
23 from .Ui_DebuggerGeneralPage import Ui_DebuggerGeneralPage |
|
24 |
|
25 import Preferences |
|
26 import Utilities |
|
27 |
|
28 |
|
29 class DebuggerGeneralPage(ConfigurationPageBase, Ui_DebuggerGeneralPage): |
|
30 """ |
|
31 Class implementing the Debugger General configuration page. |
|
32 """ |
|
33 def __init__(self): |
|
34 """ |
|
35 Constructor |
|
36 """ |
|
37 super(DebuggerGeneralPage, self).__init__() |
|
38 self.setupUi(self) |
|
39 self.setObjectName("DebuggerGeneralPage") |
|
40 |
|
41 t = self.execLineEdit.whatsThis() |
|
42 if t: |
|
43 t += Utilities.getPercentReplacementHelp() |
|
44 self.execLineEdit.setWhatsThis(t) |
|
45 |
|
46 try: |
|
47 backends = e5App().getObject("DebugServer").getSupportedLanguages() |
|
48 for backend in sorted(backends): |
|
49 self.passiveDbgBackendCombo.addItem(backend) |
|
50 except KeyError: |
|
51 self.passiveDbgGroup.setEnabled(False) |
|
52 |
|
53 t = self.consoleDbgEdit.whatsThis() |
|
54 if t: |
|
55 t += Utilities.getPercentReplacementHelp() |
|
56 self.consoleDbgEdit.setWhatsThis(t) |
|
57 |
|
58 self.consoleDbgCompleter = E5FileCompleter(self.consoleDbgEdit) |
|
59 self.dbgTranslationLocalCompleter = E5DirCompleter( |
|
60 self.dbgTranslationLocalEdit) |
|
61 |
|
62 # set initial values |
|
63 interfaces = [] |
|
64 networkInterfaces = QNetworkInterface.allInterfaces() |
|
65 for networkInterface in networkInterfaces: |
|
66 addressEntries = networkInterface.addressEntries() |
|
67 if len(addressEntries) > 0: |
|
68 for addressEntry in addressEntries: |
|
69 if ":" in addressEntry.ip().toString() and \ |
|
70 not socket.has_ipv6: |
|
71 continue # IPv6 not supported by Python |
|
72 interfaces.append( |
|
73 "{0} ({1})".format( |
|
74 networkInterface.humanReadableName(), |
|
75 addressEntry.ip().toString())) |
|
76 self.interfacesCombo.addItems(interfaces) |
|
77 interface = Preferences.getDebugger("NetworkInterface") |
|
78 if not socket.has_ipv6: |
|
79 # IPv6 not supported by Python |
|
80 self.all6InterfacesButton.setEnabled(False) |
|
81 if interface == "allv6": |
|
82 interface = "all" |
|
83 if interface == "all": |
|
84 self.allInterfacesButton.setChecked(True) |
|
85 elif interface == "allv6": |
|
86 self.all6InterfacesButton.setChecked(True) |
|
87 else: |
|
88 self.selectedInterfaceButton.setChecked(True) |
|
89 index = -1 |
|
90 for i in range(len(interfaces)): |
|
91 if QRegExp(".*{0}.*".format(interface))\ |
|
92 .exactMatch(interfaces[i]): |
|
93 index = i |
|
94 break |
|
95 self.interfacesCombo.setCurrentIndex(index) |
|
96 |
|
97 self.allowedHostsList.addItems( |
|
98 Preferences.getDebugger("AllowedHosts")) |
|
99 |
|
100 self.remoteDebuggerGroup.setChecked( |
|
101 Preferences.getDebugger("RemoteDbgEnabled")) |
|
102 self.hostLineEdit.setText( |
|
103 Preferences.getDebugger("RemoteHost")) |
|
104 self.execLineEdit.setText( |
|
105 Preferences.getDebugger("RemoteExecution")) |
|
106 |
|
107 if self.passiveDbgGroup.isEnabled(): |
|
108 self.passiveDbgCheckBox.setChecked( |
|
109 Preferences.getDebugger("PassiveDbgEnabled")) |
|
110 self.passiveDbgPortSpinBox.setValue( |
|
111 Preferences.getDebugger("PassiveDbgPort")) |
|
112 index = self.passiveDbgBackendCombo.findText( |
|
113 Preferences.getDebugger("PassiveDbgType")) |
|
114 if index == -1: |
|
115 index = 0 |
|
116 self.passiveDbgBackendCombo.setCurrentIndex(index) |
|
117 |
|
118 self.debugEnvironReplaceCheckBox.setChecked( |
|
119 Preferences.getDebugger("DebugEnvironmentReplace")) |
|
120 self.debugEnvironEdit.setText( |
|
121 Preferences.getDebugger("DebugEnvironment")) |
|
122 self.automaticResetCheckBox.setChecked( |
|
123 Preferences.getDebugger("AutomaticReset")) |
|
124 self.debugAutoSaveScriptsCheckBox.setChecked( |
|
125 Preferences.getDebugger("Autosave")) |
|
126 self.consoleDebuggerGroup.setChecked( |
|
127 Preferences.getDebugger("ConsoleDbgEnabled")) |
|
128 self.consoleDbgEdit.setText( |
|
129 Preferences.getDebugger("ConsoleDbgCommand")) |
|
130 self.dbgPathTranslationGroup.setChecked( |
|
131 Preferences.getDebugger("PathTranslation")) |
|
132 self.dbgTranslationRemoteEdit.setText( |
|
133 Preferences.getDebugger("PathTranslationRemote")) |
|
134 self.dbgTranslationLocalEdit.setText( |
|
135 Preferences.getDebugger("PathTranslationLocal")) |
|
136 self.debugThreeStateBreakPoint.setChecked( |
|
137 Preferences.getDebugger("ThreeStateBreakPoints")) |
|
138 self.recentFilesSpinBox.setValue( |
|
139 Preferences.getDebugger("RecentNumber")) |
|
140 self.dontShowClientExitCheckBox.setChecked( |
|
141 Preferences.getDebugger("SuppressClientExit")) |
|
142 self.exceptionBreakCheckBox.setChecked( |
|
143 Preferences.getDebugger("BreakAlways")) |
|
144 self.exceptionShellCheckBox.setChecked( |
|
145 Preferences.getDebugger("ShowExceptionInShell")) |
|
146 self.autoViewSourcecodeCheckBox.setChecked( |
|
147 Preferences.getDebugger("AutoViewSourceCode")) |
|
148 self.maxSizeSpinBox.setValue( |
|
149 Preferences.getDebugger("MaxVariableSize")) |
|
150 |
|
151 def save(self): |
|
152 """ |
|
153 Public slot to save the Debugger General (1) configuration. |
|
154 """ |
|
155 Preferences.setDebugger( |
|
156 "RemoteDbgEnabled", |
|
157 self.remoteDebuggerGroup.isChecked()) |
|
158 Preferences.setDebugger( |
|
159 "RemoteHost", |
|
160 self.hostLineEdit.text()) |
|
161 Preferences.setDebugger( |
|
162 "RemoteExecution", |
|
163 self.execLineEdit.text()) |
|
164 |
|
165 Preferences.setDebugger( |
|
166 "PassiveDbgEnabled", |
|
167 self.passiveDbgCheckBox.isChecked()) |
|
168 Preferences.setDebugger( |
|
169 "PassiveDbgPort", |
|
170 self.passiveDbgPortSpinBox.value()) |
|
171 Preferences.setDebugger( |
|
172 "PassiveDbgType", |
|
173 self.passiveDbgBackendCombo.currentText()) |
|
174 |
|
175 if self.allInterfacesButton.isChecked(): |
|
176 Preferences.setDebugger("NetworkInterface", "all") |
|
177 elif self.all6InterfacesButton.isChecked(): |
|
178 Preferences.setDebugger("NetworkInterface", "allv6") |
|
179 else: |
|
180 interface = self.interfacesCombo.currentText() |
|
181 interface = interface.split("(")[1].split(")")[0] |
|
182 if not interface: |
|
183 Preferences.setDebugger("NetworkInterface", "all") |
|
184 else: |
|
185 Preferences.setDebugger("NetworkInterface", interface) |
|
186 |
|
187 allowedHosts = [] |
|
188 for row in range(self.allowedHostsList.count()): |
|
189 allowedHosts.append(self.allowedHostsList.item(row).text()) |
|
190 Preferences.setDebugger("AllowedHosts", allowedHosts) |
|
191 |
|
192 Preferences.setDebugger( |
|
193 "DebugEnvironmentReplace", |
|
194 self.debugEnvironReplaceCheckBox.isChecked()) |
|
195 Preferences.setDebugger( |
|
196 "DebugEnvironment", |
|
197 self.debugEnvironEdit.text()) |
|
198 Preferences.setDebugger( |
|
199 "AutomaticReset", |
|
200 self.automaticResetCheckBox.isChecked()) |
|
201 Preferences.setDebugger( |
|
202 "Autosave", |
|
203 self.debugAutoSaveScriptsCheckBox.isChecked()) |
|
204 Preferences.setDebugger( |
|
205 "ConsoleDbgEnabled", |
|
206 self.consoleDebuggerGroup.isChecked()) |
|
207 Preferences.setDebugger( |
|
208 "ConsoleDbgCommand", |
|
209 self.consoleDbgEdit.text()) |
|
210 Preferences.setDebugger( |
|
211 "PathTranslation", |
|
212 self.dbgPathTranslationGroup.isChecked()) |
|
213 Preferences.setDebugger( |
|
214 "PathTranslationRemote", |
|
215 self.dbgTranslationRemoteEdit.text()) |
|
216 Preferences.setDebugger( |
|
217 "PathTranslationLocal", |
|
218 self.dbgTranslationLocalEdit.text()) |
|
219 Preferences.setDebugger( |
|
220 "ThreeStateBreakPoints", |
|
221 self.debugThreeStateBreakPoint.isChecked()) |
|
222 Preferences.setDebugger( |
|
223 "RecentNumber", |
|
224 self.recentFilesSpinBox.value()) |
|
225 Preferences.setDebugger( |
|
226 "SuppressClientExit", |
|
227 self.dontShowClientExitCheckBox.isChecked()) |
|
228 Preferences.setDebugger( |
|
229 "BreakAlways", |
|
230 self.exceptionBreakCheckBox.isChecked()) |
|
231 Preferences.setDebugger( |
|
232 "ShowExceptionInShell", |
|
233 self.exceptionShellCheckBox.isChecked()) |
|
234 Preferences.setDebugger( |
|
235 "AutoViewSourceCode", |
|
236 self.autoViewSourcecodeCheckBox.isChecked()) |
|
237 Preferences.setDebugger( |
|
238 "MaxVariableSize", |
|
239 self.maxSizeSpinBox.value()) |
|
240 |
|
241 def on_allowedHostsList_currentItemChanged(self, current, previous): |
|
242 """ |
|
243 Private method set the state of the edit and delete button. |
|
244 |
|
245 @param current new current item (QListWidgetItem) |
|
246 @param previous previous current item (QListWidgetItem) |
|
247 """ |
|
248 self.editAllowedHostButton.setEnabled(current is not None) |
|
249 self.deleteAllowedHostButton.setEnabled(current is not None) |
|
250 |
|
251 @pyqtSlot() |
|
252 def on_addAllowedHostButton_clicked(self): |
|
253 """ |
|
254 Private slot called to add a new allowed host. |
|
255 """ |
|
256 allowedHost, ok = QInputDialog.getText( |
|
257 None, |
|
258 self.tr("Add allowed host"), |
|
259 self.tr("Enter the IP address of an allowed host"), |
|
260 QLineEdit.Normal) |
|
261 if ok and allowedHost: |
|
262 if QHostAddress(allowedHost).protocol() in \ |
|
263 [QAbstractSocket.IPv4Protocol, QAbstractSocket.IPv6Protocol]: |
|
264 self.allowedHostsList.addItem(allowedHost) |
|
265 else: |
|
266 E5MessageBox.critical( |
|
267 self, |
|
268 self.tr("Add allowed host"), |
|
269 self.tr( |
|
270 """<p>The entered address <b>{0}</b> is not""" |
|
271 """ a valid IP v4 or IP v6 address.""" |
|
272 """ Aborting...</p>""") |
|
273 .format(allowedHost)) |
|
274 |
|
275 @pyqtSlot() |
|
276 def on_deleteAllowedHostButton_clicked(self): |
|
277 """ |
|
278 Private slot called to delete an allowed host. |
|
279 """ |
|
280 self.allowedHostsList.takeItem(self.allowedHostsList.currentRow()) |
|
281 |
|
282 @pyqtSlot() |
|
283 def on_editAllowedHostButton_clicked(self): |
|
284 """ |
|
285 Private slot called to edit an allowed host. |
|
286 """ |
|
287 allowedHost = self.allowedHostsList.currentItem().text() |
|
288 allowedHost, ok = QInputDialog.getText( |
|
289 None, |
|
290 self.tr("Edit allowed host"), |
|
291 self.tr("Enter the IP address of an allowed host"), |
|
292 QLineEdit.Normal, |
|
293 allowedHost) |
|
294 if ok and allowedHost: |
|
295 if QHostAddress(allowedHost).protocol() in \ |
|
296 [QAbstractSocket.IPv4Protocol, QAbstractSocket.IPv6Protocol]: |
|
297 self.allowedHostsList.currentItem().setText(allowedHost) |
|
298 else: |
|
299 E5MessageBox.critical( |
|
300 self, |
|
301 self.tr("Edit allowed host"), |
|
302 self.tr( |
|
303 """<p>The entered address <b>{0}</b> is not""" |
|
304 """ a valid IP v4 or IP v6 address.""" |
|
305 """ Aborting...</p>""") |
|
306 .format(allowedHost)) |
|
307 |
|
308 |
|
309 def create(dlg): |
|
310 """ |
|
311 Module function to create the configuration page. |
|
312 |
|
313 @param dlg reference to the configuration dialog |
|
314 @return reference to the instantiated page (ConfigurationPageBase) |
|
315 """ |
|
316 page = DebuggerGeneralPage() |
|
317 return page |