eric7/Preferences/ConfigurationPages/DebuggerGeneralPage.py

branch
eric7
changeset 8312
800c432b34c8
parent 8218
7c09585bd960
child 8318
962bce857696
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2006 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the Debugger General configuration page.
8 """
9
10 import re
11 import socket
12
13 from PyQt5.QtCore import pyqtSlot, Qt, QAbstractItemModel, QModelIndex
14 from PyQt5.QtGui import QBrush, QColor
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().__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 (
70 ":" in addressEntry.ip().toString() and
71 not socket.has_ipv6
72 ):
73 continue # IPv6 not supported by Python
74 interfaces.append(
75 "{0} ({1})".format(
76 networkInterface.humanReadableName(),
77 addressEntry.ip().toString()))
78 self.interfacesCombo.addItems(interfaces)
79 interface = Preferences.getDebugger("NetworkInterface")
80 if not socket.has_ipv6:
81 # IPv6 not supported by Python
82 self.all6InterfacesButton.setEnabled(False)
83 if interface == "allv6":
84 interface = "all"
85 if interface == "all":
86 self.allInterfacesButton.setChecked(True)
87 elif interface == "allv6":
88 self.all6InterfacesButton.setChecked(True)
89 else:
90 self.selectedInterfaceButton.setChecked(True)
91 index = -1
92 for i in range(len(interfaces)):
93 if (
94 re.fullmatch(".*{0}.*".format(interface), interfaces[i])
95 ):
96 index = i
97 break
98 self.interfacesCombo.setCurrentIndex(index)
99
100 self.allowedHostsList.addItems(
101 Preferences.getDebugger("AllowedHosts"))
102
103 self.remoteDebuggerGroup.setChecked(
104 Preferences.getDebugger("RemoteDbgEnabled"))
105 self.hostLineEdit.setText(
106 Preferences.getDebugger("RemoteHost"))
107 self.execLineEdit.setText(
108 Preferences.getDebugger("RemoteExecution"))
109
110 if self.passiveDbgGroup.isEnabled():
111 self.passiveDbgCheckBox.setChecked(
112 Preferences.getDebugger("PassiveDbgEnabled"))
113 self.passiveDbgPortSpinBox.setValue(
114 Preferences.getDebugger("PassiveDbgPort"))
115 index = self.passiveDbgBackendCombo.findText(
116 Preferences.getDebugger("PassiveDbgType"))
117 if index == -1:
118 index = 0
119 self.passiveDbgBackendCombo.setCurrentIndex(index)
120
121 self.debugEnvironReplaceCheckBox.setChecked(
122 Preferences.getDebugger("DebugEnvironmentReplace"))
123 self.debugEnvironEdit.setText(
124 Preferences.getDebugger("DebugEnvironment"))
125 self.automaticResetCheckBox.setChecked(
126 Preferences.getDebugger("AutomaticReset"))
127 self.debugAutoSaveScriptsCheckBox.setChecked(
128 Preferences.getDebugger("Autosave"))
129 self.consoleDebuggerGroup.setChecked(
130 Preferences.getDebugger("ConsoleDbgEnabled"))
131 self.consoleDbgEdit.setText(
132 Preferences.getDebugger("ConsoleDbgCommand"))
133 self.dbgPathTranslationGroup.setChecked(
134 Preferences.getDebugger("PathTranslation"))
135 self.dbgTranslationRemoteEdit.setText(
136 Preferences.getDebugger("PathTranslationRemote"))
137 self.dbgTranslationLocalEdit.setText(
138 Preferences.getDebugger("PathTranslationLocal"))
139 self.multiprocessCheckBox.setChecked(
140 Preferences.getDebugger("MultiProcessEnabled"))
141 self.debugThreeStateBreakPoint.setChecked(
142 Preferences.getDebugger("ThreeStateBreakPoints"))
143 self.recentFilesSpinBox.setValue(
144 Preferences.getDebugger("RecentNumber"))
145 self.exceptionBreakCheckBox.setChecked(
146 Preferences.getDebugger("BreakAlways"))
147 self.exceptionShellCheckBox.setChecked(
148 Preferences.getDebugger("ShowExceptionInShell"))
149 self.maxSizeSpinBox.setValue(
150 Preferences.getDebugger("MaxVariableSize"))
151 # Set the colours for debug viewer backgrounds
152 self.previewMdl = PreviewModel()
153 self.preView.setModel(self.previewMdl)
154 self.colourChanged.connect(self.previewMdl.setColor)
155 self.initColour("BgColorNew", self.backgroundNewButton,
156 Preferences.getDebugger, hasAlpha=True)
157 self.initColour("BgColorChanged", self.backgroundChangedButton,
158 Preferences.getDebugger, hasAlpha=True)
159
160 self.autoViewSourcecodeCheckBox.setChecked(
161 Preferences.getDebugger("AutoViewSourceCode"))
162
163 def save(self):
164 """
165 Public slot to save the Debugger General (1) configuration.
166 """
167 Preferences.setDebugger(
168 "RemoteDbgEnabled",
169 self.remoteDebuggerGroup.isChecked())
170 Preferences.setDebugger(
171 "RemoteHost",
172 self.hostLineEdit.text())
173 Preferences.setDebugger(
174 "RemoteExecution",
175 self.execLineEdit.text())
176
177 Preferences.setDebugger(
178 "PassiveDbgEnabled",
179 self.passiveDbgCheckBox.isChecked())
180 Preferences.setDebugger(
181 "PassiveDbgPort",
182 self.passiveDbgPortSpinBox.value())
183 Preferences.setDebugger(
184 "PassiveDbgType",
185 self.passiveDbgBackendCombo.currentText())
186
187 if self.allInterfacesButton.isChecked():
188 Preferences.setDebugger("NetworkInterface", "all")
189 elif self.all6InterfacesButton.isChecked():
190 Preferences.setDebugger("NetworkInterface", "allv6")
191 else:
192 interface = self.interfacesCombo.currentText()
193 interface = interface.split("(")[1].split(")")[0]
194 if not interface:
195 Preferences.setDebugger("NetworkInterface", "all")
196 else:
197 Preferences.setDebugger("NetworkInterface", interface)
198
199 allowedHosts = []
200 for row in range(self.allowedHostsList.count()):
201 allowedHosts.append(self.allowedHostsList.item(row).text())
202 Preferences.setDebugger("AllowedHosts", allowedHosts)
203
204 Preferences.setDebugger(
205 "DebugEnvironmentReplace",
206 self.debugEnvironReplaceCheckBox.isChecked())
207 Preferences.setDebugger(
208 "DebugEnvironment",
209 self.debugEnvironEdit.text())
210 Preferences.setDebugger(
211 "AutomaticReset",
212 self.automaticResetCheckBox.isChecked())
213 Preferences.setDebugger(
214 "Autosave",
215 self.debugAutoSaveScriptsCheckBox.isChecked())
216 Preferences.setDebugger(
217 "ConsoleDbgEnabled",
218 self.consoleDebuggerGroup.isChecked())
219 Preferences.setDebugger(
220 "ConsoleDbgCommand",
221 self.consoleDbgEdit.text())
222 Preferences.setDebugger(
223 "PathTranslation",
224 self.dbgPathTranslationGroup.isChecked())
225 Preferences.setDebugger(
226 "PathTranslationRemote",
227 self.dbgTranslationRemoteEdit.text())
228 Preferences.setDebugger(
229 "PathTranslationLocal",
230 self.dbgTranslationLocalEdit.text())
231 Preferences.setDebugger(
232 "MultiProcessEnabled",
233 self.multiprocessCheckBox.isChecked())
234 Preferences.setDebugger(
235 "ThreeStateBreakPoints",
236 self.debugThreeStateBreakPoint.isChecked())
237 Preferences.setDebugger(
238 "RecentNumber",
239 self.recentFilesSpinBox.value())
240 Preferences.setDebugger(
241 "BreakAlways",
242 self.exceptionBreakCheckBox.isChecked())
243 Preferences.setDebugger(
244 "ShowExceptionInShell",
245 self.exceptionShellCheckBox.isChecked())
246 Preferences.setDebugger(
247 "MaxVariableSize",
248 self.maxSizeSpinBox.value())
249 # Store background colors for debug viewer
250 self.saveColours(Preferences.setDebugger)
251
252 Preferences.setDebugger(
253 "AutoViewSourceCode",
254 self.autoViewSourcecodeCheckBox.isChecked())
255
256 def on_allowedHostsList_currentItemChanged(self, current, previous):
257 """
258 Private method set the state of the edit and delete button.
259
260 @param current new current item (QListWidgetItem)
261 @param previous previous current item (QListWidgetItem)
262 """
263 self.editAllowedHostButton.setEnabled(current is not None)
264 self.deleteAllowedHostButton.setEnabled(current is not None)
265
266 @pyqtSlot()
267 def on_addAllowedHostButton_clicked(self):
268 """
269 Private slot called to add a new allowed host.
270 """
271 allowedHost, ok = QInputDialog.getText(
272 None,
273 self.tr("Add allowed host"),
274 self.tr("Enter the IP address of an allowed host"),
275 QLineEdit.EchoMode.Normal)
276 if ok and allowedHost:
277 if QHostAddress(allowedHost).protocol() in [
278 QAbstractSocket.NetworkLayerProtocol.IPv4Protocol,
279 QAbstractSocket.NetworkLayerProtocol.IPv6Protocol
280 ]:
281 self.allowedHostsList.addItem(allowedHost)
282 else:
283 E5MessageBox.critical(
284 self,
285 self.tr("Add allowed host"),
286 self.tr(
287 """<p>The entered address <b>{0}</b> is not"""
288 """ a valid IP v4 or IP v6 address."""
289 """ Aborting...</p>""")
290 .format(allowedHost))
291
292 @pyqtSlot()
293 def on_deleteAllowedHostButton_clicked(self):
294 """
295 Private slot called to delete an allowed host.
296 """
297 self.allowedHostsList.takeItem(self.allowedHostsList.currentRow())
298
299 @pyqtSlot()
300 def on_editAllowedHostButton_clicked(self):
301 """
302 Private slot called to edit an allowed host.
303 """
304 allowedHost = self.allowedHostsList.currentItem().text()
305 allowedHost, ok = QInputDialog.getText(
306 None,
307 self.tr("Edit allowed host"),
308 self.tr("Enter the IP address of an allowed host"),
309 QLineEdit.EchoMode.Normal,
310 allowedHost)
311 if ok and allowedHost:
312 if QHostAddress(allowedHost).protocol() in [
313 QAbstractSocket.NetworkLayerProtocol.IPv4Protocol,
314 QAbstractSocket.NetworkLayerProtocol.IPv6Protocol
315 ]:
316 self.allowedHostsList.currentItem().setText(allowedHost)
317 else:
318 E5MessageBox.critical(
319 self,
320 self.tr("Edit allowed host"),
321 self.tr(
322 """<p>The entered address <b>{0}</b> is not"""
323 """ a valid IP v4 or IP v6 address."""
324 """ Aborting...</p>""")
325 .format(allowedHost))
326
327
328 class PreviewModel(QAbstractItemModel):
329 """
330 Class to show an example of the selected background colours for the debug
331 viewer.
332 """
333 def __init__(self):
334 """
335 Constructor
336 """
337 super().__init__()
338 self.bgColorNew = QBrush(QColor('#FFFFFF'))
339 self.bgColorChanged = QBrush(QColor('#FFFFFF'))
340
341 def setColor(self, key, bgcolour):
342 """
343 Public slot to update the background colour indexed by key.
344
345 @param key the name of background
346 @type str
347 @param bgcolour the new background colour
348 @type QColor
349 """
350 if key == 'BgColorNew':
351 self.bgColorNew = QBrush(bgcolour)
352 else:
353 self.bgColorChanged = QBrush(bgcolour)
354
355 # Force update of preview view
356 idxStart = self.index(0, 0, QModelIndex())
357 idxEnd = self.index(0, 2, QModelIndex())
358 self.dataChanged.emit(idxStart, idxEnd)
359
360 def index(self, row, column, parent=QModelIndex()):
361 """
362 Public Qt slot to get the index of item at row:column of parent.
363
364 @param row number of rows
365 @type int
366 @param column number of columns
367 @type int
368 @param parent the model parent
369 @type QModelIndex
370 @return new model index for child
371 @rtype QModelIndex
372 """
373 if not self.hasIndex(row, column, parent):
374 return QModelIndex()
375
376 return self.createIndex(row, column, None)
377
378 def parent(self, child):
379 """
380 Public Qt slot to get the parent of the given child.
381
382 @param child the model child node
383 @type QModelIndex
384 @return new model index for parent
385 @rtype QModelIndex
386 """
387 return QModelIndex()
388
389 def columnCount(self, parent=QModelIndex()):
390 """
391 Public Qt slot to get the column count.
392
393 @param parent the model parent
394 @type QModelIndex
395 @return number of columns
396 @rtype int
397 """
398 return 1
399
400 def rowCount(self, parent=QModelIndex()):
401 """
402 Public Qt slot to get the row count.
403
404 @param parent the model parent
405 @type QModelIndex
406 @return number of rows
407 @rtype int
408 """
409 return 4
410
411 def flags(self, index):
412 """
413 Public Qt slot to get the item flags.
414
415 @param index of item
416 @type QModelIndex
417 @return item flags
418 @rtype QtCore.Qt.ItemFlag
419 """
420 return Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable
421
422 def data(self, index, role=Qt.ItemDataRole.DisplayRole):
423 """
424 Public Qt slot get the role data of item.
425
426 @param index the model index
427 @type QModelIndex
428 @param role the requested data role
429 @type QtCore.Qt.ItemDataRole
430 @return role data of item
431 @rtype str, QBrush or None
432 """
433 if role == Qt.ItemDataRole.DisplayRole:
434 return self.tr("Variable Name")
435 elif role == Qt.ItemDataRole.BackgroundRole:
436 if index.row() >= 2:
437 return self.bgColorChanged
438 else:
439 return self.bgColorNew
440
441 return None
442
443
444 def create(dlg):
445 """
446 Module function to create the configuration page.
447
448 @param dlg reference to the configuration dialog
449 @return reference to the instantiated page (ConfigurationPageBase)
450 """
451 return DebuggerGeneralPage()
452
453 #
454 # eflag: noqa = M822

eric ide

mercurial