11 |
11 |
12 import os |
12 import os |
13 |
13 |
14 from PyQt5.QtCore import pyqtSignal, QObject, Qt |
14 from PyQt5.QtCore import pyqtSignal, QObject, Qt |
15 from PyQt5.QtGui import QKeySequence |
15 from PyQt5.QtGui import QKeySequence |
16 from PyQt5.QtWidgets import QMenu, QToolBar, QApplication, QDialog, \ |
16 from PyQt5.QtWidgets import QMenu, QToolBar, QApplication, QDialog |
17 QInputDialog |
|
18 |
17 |
19 from UI.Info import Program |
18 from UI.Info import Program |
20 |
19 |
21 from .DebugClientCapabilities import HasDebugger, HasInterpreter, \ |
20 from .DebugClientCapabilities import HasDebugger, HasInterpreter, \ |
22 HasProfiler, HasCoverage |
21 HasProfiler, HasCoverage |
102 Preferences.Prefs.settings.value( |
101 Preferences.Prefs.settings.value( |
103 'DebugInfo/ForkAutomatically', False)) |
102 'DebugInfo/ForkAutomatically', False)) |
104 self.forkIntoChild = Preferences.toBool( |
103 self.forkIntoChild = Preferences.toBool( |
105 Preferences.Prefs.settings.value('DebugInfo/ForkIntoChild', False)) |
104 Preferences.Prefs.settings.value('DebugInfo/ForkIntoChild', False)) |
106 |
105 |
107 self.evalHistory = [] |
|
108 self.execHistory = [] |
|
109 self.lastDebuggedFile = None |
106 self.lastDebuggedFile = None |
110 self.lastStartAction = 0 # 0=None, 1=Script, 2=Project |
107 self.lastStartAction = 0 # 0=None, 1=Script, 2=Project |
111 self.clientType = "" |
108 self.clientType = "" |
112 self.lastAction = -1 |
109 self.lastAction = -1 |
113 self.debugActions = [ |
110 self.debugActions = [ |
426 """<p>Stop the running debugging session.</p>""" |
423 """<p>Stop the running debugging session.</p>""" |
427 )) |
424 )) |
428 act.triggered.connect(self.__stepQuit) |
425 act.triggered.connect(self.__stepQuit) |
429 self.actions.append(act) |
426 self.actions.append(act) |
430 |
427 |
431 self.debugActGrp2 = createActionGroup(self) |
|
432 |
|
433 act = E5Action( |
|
434 self.tr('Evaluate'), |
|
435 self.tr('E&valuate...'), |
|
436 0, 0, self.debugActGrp2, 'dbg_evaluate') |
|
437 act.setStatusTip(self.tr('Evaluate in current context')) |
|
438 act.setWhatsThis(self.tr( |
|
439 """<b>Evaluate</b>""" |
|
440 """<p>Evaluate an expression in the current context of the""" |
|
441 """ debugged program. The result is displayed in the""" |
|
442 """ shell window.</p>""" |
|
443 )) |
|
444 act.triggered.connect(self.__eval) |
|
445 self.actions.append(act) |
|
446 |
|
447 act = E5Action( |
|
448 self.tr('Execute'), |
|
449 self.tr('E&xecute...'), |
|
450 0, 0, self.debugActGrp2, 'dbg_execute') |
|
451 act.setStatusTip( |
|
452 self.tr('Execute a one line statement in the current context')) |
|
453 act.setWhatsThis(self.tr( |
|
454 """<b>Execute</b>""" |
|
455 """<p>Execute a one line statement in the current context""" |
|
456 """ of the debugged program.</p>""" |
|
457 )) |
|
458 act.triggered.connect(self.__exec) |
|
459 self.actions.append(act) |
|
460 |
|
461 self.dbgFilterAct = E5Action( |
428 self.dbgFilterAct = E5Action( |
462 self.tr('Variables Type Filter'), |
429 self.tr('Variables Type Filter'), |
463 self.tr('Varia&bles Type Filter...'), 0, 0, self, |
430 self.tr('Varia&bles Type Filter...'), 0, 0, self, |
464 'dbg_variables_filter') |
431 'dbg_variables_filter') |
465 self.dbgFilterAct.setStatusTip(self.tr( |
432 self.dbgFilterAct.setStatusTip(self.tr( |
804 self.debugAct.setEnabled(False) |
768 self.debugAct.setEnabled(False) |
805 self.runAct.setEnabled(False) |
769 self.runAct.setEnabled(False) |
806 self.profileAct.setEnabled(False) |
770 self.profileAct.setEnabled(False) |
807 self.coverageAct.setEnabled(False) |
771 self.coverageAct.setEnabled(False) |
808 self.debugActGrp.setEnabled(False) |
772 self.debugActGrp.setEnabled(False) |
809 self.debugActGrp2.setEnabled(False) |
|
810 self.dbgSetBpActGrp.setEnabled(False) |
773 self.dbgSetBpActGrp.setEnabled(False) |
811 self.lastAction = -1 |
774 self.lastAction = -1 |
812 if not self.projectOpen: |
775 if not self.projectOpen: |
813 self.restartAct.setEnabled(False) |
776 self.restartAct.setEnabled(False) |
814 self.lastDebuggedFile = None |
777 self.lastDebuggedFile = None |
1014 if not forStack: |
976 if not forStack: |
1015 self.__getThreadList() |
977 self.__getThreadList() |
1016 self.__getClientVariables() |
978 self.__getClientVariables() |
1017 |
979 |
1018 self.debugActGrp.setEnabled(True) |
980 self.debugActGrp.setEnabled(True) |
1019 self.debugActGrp2.setEnabled(True) |
981 |
1020 |
982 def __clientExit(self, status, message): |
1021 def __clientExit(self, status): |
|
1022 """ |
983 """ |
1023 Private method to handle the debugged program terminating. |
984 Private method to handle the debugged program terminating. |
1024 |
985 |
1025 @param status exit code of the debugged program (int) |
986 @param status exit code of the debugged program |
|
987 @type int |
|
988 @param message exit message of the debugged program |
|
989 @type str |
1026 """ |
990 """ |
1027 self.viewmanager.exit() |
991 self.viewmanager.exit() |
1028 |
992 |
1029 self.__resetUI() |
993 self.__resetUI() |
1030 |
994 |
1031 if not Preferences.getDebugger("SuppressClientExit") or status != 0: |
995 if not Preferences.getDebugger("SuppressClientExit") or status != 0: |
|
996 if message: |
|
997 info = self.tr("<p>Message: {0}</p>").format( |
|
998 Utilities.html_uencode(message)) |
|
999 else: |
|
1000 info = "" |
1032 if self.ui.currentProg is None: |
1001 if self.ui.currentProg is None: |
1033 E5MessageBox.information( |
1002 E5MessageBox.information( |
1034 self.ui, Program, |
1003 self.ui, Program, |
1035 self.tr('<p>The program has terminated with an exit' |
1004 self.tr('<p>The program has terminated with an exit' |
1036 ' status of {0}.</p>').format(status)) |
1005 ' status of {0}.</p>{1}').format(status, info)) |
1037 else: |
1006 else: |
1038 E5MessageBox.information( |
1007 E5MessageBox.information( |
1039 self.ui, Program, |
1008 self.ui, Program, |
1040 self.tr('<p><b>{0}</b> has terminated with an exit' |
1009 self.tr('<p><b>{0}</b> has terminated with an exit' |
1041 ' status of {1}.</p>') |
1010 ' status of {1}.</p>{2}') |
1042 .format(Utilities.normabspath(self.ui.currentProg), |
1011 .format(Utilities.normabspath(self.ui.currentProg), |
1043 status)) |
1012 status, info)) |
1044 else: |
1013 else: |
|
1014 if message: |
|
1015 info = self.tr("Message: {0}").format( |
|
1016 Utilities.html_uencode(message)) |
|
1017 else: |
|
1018 info = "" |
1045 if self.ui.notificationsEnabled(): |
1019 if self.ui.notificationsEnabled(): |
1046 if self.ui.currentProg is None: |
1020 if self.ui.currentProg is None: |
1047 msg = self.tr('The program has terminated with an exit' |
1021 msg = self.tr('The program has terminated with an exit' |
1048 ' status of {0}.').format(status) |
1022 ' status of {0}.\n{1}').format(status, info) |
1049 else: |
1023 else: |
1050 msg = self.tr('"{0}" has terminated with an exit' |
1024 msg = self.tr('"{0}" has terminated with an exit' |
1051 ' status of {1}.')\ |
1025 ' status of {1}.\n{2}')\ |
1052 .format(os.path.basename(self.ui.currentProg), |
1026 .format(os.path.basename(self.ui.currentProg), |
1053 status) |
1027 status, info) |
1054 self.ui.showNotification( |
1028 self.ui.showNotification( |
1055 UI.PixmapCache.getPixmap("debug48.png"), |
1029 UI.PixmapCache.getPixmap("debug48.png"), |
1056 self.tr("Program terminated"), msg) |
1030 self.tr("Program terminated"), msg) |
1057 else: |
1031 else: |
1058 if self.ui.currentProg is None: |
1032 if self.ui.currentProg is None: |
1059 self.appendStdout.emit( |
1033 self.appendStdout.emit( |
1060 self.tr('The program has terminated with an exit' |
1034 self.tr('The program has terminated with an exit' |
1061 ' status of {0}.\n').format(status)) |
1035 ' status of {0}.\n{1}\n').format(status, info)) |
1062 else: |
1036 else: |
1063 self.appendStdout.emit( |
1037 self.appendStdout.emit( |
1064 self.tr('"{0}" has terminated with an exit' |
1038 self.tr('"{0}" has terminated with an exit' |
1065 ' status of {1}.\n') |
1039 ' status of {1}.\n{2}\n') |
1066 .format(Utilities.normabspath(self.ui.currentProg), |
1040 .format(Utilities.normabspath(self.ui.currentProg), |
1067 status)) |
1041 status, info)) |
1068 |
1042 |
1069 def __clientSyntaxError(self, message, filename, lineNo, characterNo): |
1043 def __clientSyntaxError(self, message, filename, lineNo, characterNo): |
1070 """ |
1044 """ |
1071 Private method to handle a syntax error in the debugged program. |
1045 Private method to handle a syntax error in the debugged program. |
1072 |
1046 |
1190 stack.append((fn, ln, func, args)) |
1164 stack.append((fn, ln, func, args)) |
1191 self.clientStack.emit(stack) |
1165 self.clientStack.emit(stack) |
1192 self.__getClientVariables() |
1166 self.__getClientVariables() |
1193 self.ui.setDebugProfile() |
1167 self.ui.setDebugProfile() |
1194 self.debugActGrp.setEnabled(True) |
1168 self.debugActGrp.setEnabled(True) |
1195 self.debugActGrp2.setEnabled(True) |
|
1196 return |
1169 return |
1197 elif res == E5MessageBox.Ignore: |
1170 elif res == E5MessageBox.Ignore: |
1198 if exceptionType not in self.excIgnoreList: |
1171 if exceptionType not in self.excIgnoreList: |
1199 self.excIgnoreList.append(exceptionType) |
1172 self.excIgnoreList.append(exceptionType) |
1200 |
1173 |
2190 self.__enterRemote() |
2163 self.__enterRemote() |
2191 self.debugServer.remoteBreakpoint( |
2164 self.debugServer.remoteBreakpoint( |
2192 aw.getFileName(), line, 1, None, 1) |
2165 aw.getFileName(), line, 1, None, 1) |
2193 self.debugServer.remoteContinue() |
2166 self.debugServer.remoteContinue() |
2194 |
2167 |
2195 def __eval(self): |
|
2196 """ |
|
2197 Private method to handle the Eval action. |
|
2198 """ |
|
2199 # Get the command line arguments. |
|
2200 if len(self.evalHistory) > 0: |
|
2201 curr = 0 |
|
2202 else: |
|
2203 curr = -1 |
|
2204 |
|
2205 arg, ok = QInputDialog.getItem( |
|
2206 self.ui, |
|
2207 self.tr("Evaluate"), |
|
2208 self.tr("Enter the statement to evaluate"), |
|
2209 self.evalHistory, |
|
2210 curr, True) |
|
2211 |
|
2212 if ok: |
|
2213 if not arg: |
|
2214 return |
|
2215 |
|
2216 # This moves any previous occurrence of this expression to the head |
|
2217 # of the list. |
|
2218 if arg in self.evalHistory: |
|
2219 self.evalHistory.remove(arg) |
|
2220 self.evalHistory.insert(0, arg) |
|
2221 |
|
2222 self.debugServer.remoteEval(arg) |
|
2223 |
|
2224 def __exec(self): |
|
2225 """ |
|
2226 Private method to handle the Exec action. |
|
2227 """ |
|
2228 # Get the command line arguments. |
|
2229 if len(self.execHistory) > 0: |
|
2230 curr = 0 |
|
2231 else: |
|
2232 curr = -1 |
|
2233 |
|
2234 stmt, ok = QInputDialog.getItem( |
|
2235 self.ui, |
|
2236 self.tr("Execute"), |
|
2237 self.tr("Enter the statement to execute"), |
|
2238 self.execHistory, |
|
2239 curr, True) |
|
2240 |
|
2241 if ok: |
|
2242 if not stmt: |
|
2243 return |
|
2244 |
|
2245 # This moves any previous occurrence of this statement to the head |
|
2246 # of the list. |
|
2247 if stmt in self.execHistory: |
|
2248 self.execHistory.remove(stmt) |
|
2249 self.execHistory.insert(0, stmt) |
|
2250 |
|
2251 self.debugServer.remoteExec(stmt) |
|
2252 |
|
2253 def __enterRemote(self): |
2168 def __enterRemote(self): |
2254 """ |
2169 """ |
2255 Private method to update the user interface. |
2170 Private method to update the user interface. |
2256 |
2171 |
2257 This method is called just prior to executing some of |
2172 This method is called just prior to executing some of |
2258 the program being debugged. |
2173 the program being debugged. |
2259 """ |
2174 """ |
2260 # Disable further debug commands from the user. |
2175 # Disable further debug commands from the user. |
2261 self.debugActGrp.setEnabled(False) |
2176 self.debugActGrp.setEnabled(False) |
2262 self.debugActGrp2.setEnabled(False) |
|
2263 |
2177 |
2264 self.viewmanager.unhighlight(True) |
2178 self.viewmanager.unhighlight(True) |
2265 |
2179 |
2266 def getActions(self): |
2180 def getActions(self): |
2267 """ |
2181 """ |