def validateBreakpoints(self): """Checks breakpoints and deletes those which are invalid""" if not self.__breakpoints: return fileName = self._qpart._parent.getFileName() breakableLines = getBreakpointLines(fileName, self._qpart.text, True, False) toBeDeleted = [] for _, bpoint in self.__breakpoints.items(): bpointLine = bpoint.getLineNumber() if breakableLines is None or bpointLine not in breakableLines: toBeDeleted.append(bpointLine) if toBeDeleted: model = self.__debugger.getBreakPointModel() for line in toBeDeleted: location = ':'.join([fileName, str(line)]) if breakableLines is None: msg = 'Breakpoint at ' + location + ' does not point to ' \ 'a breakable line (file is not compilable).' else: msg = 'Breakpoint at ' + location + ' does not point to ' \ 'a breakable line anymore.' logging.warning(msg + ' The breakpoint is deleted.') index = model.getBreakPointIndex(fileName, line) self.setBlockValue( self._qpart.document().findBlockByNumber(line - 1), 0) model.deleteBreakPointByIndex(index)
def isLineBreakable(self, line=None, enforceRecalc=False, enforceSure=False): """True if a breakpoint could be placed on the current line""" fileName = self._qpart._parent.getFileName() if fileName is None or fileName == "" or not os.path.isabs(fileName): return False if not self._qpart.isPythonBuffer(): return False if line is None: curPos = self._qpart.cursorPosition line = curPos[0] + 1 if self.__breakableLines is not None and not enforceRecalc: return line in self.__breakableLines self.__breakableLines = getBreakpointLines(fileName, self._qpart.text, enforceRecalc) if self.__breakableLines is None: if not enforceSure: # Be on the safe side - if there is a problem of # getting the breakable lines, let the user decide return True return False return line in self.__breakableLines
def __onBlockClicked(self, block): """Margin of the block has been clicked""" lineNo = block.blockNumber() + 1 for _, bpoint in self.__breakpoints.items(): if bpoint.getLineNumber() == lineNo: # Breakpoint marker is set for this line already self.__toggleBreakpoint(lineNo) return # Check if it is a python file if not self._qpart.isPythonBuffer(): return fileName = self._qpart._parent.getFileName() if fileName is None or fileName == "" or not os.path.isabs(fileName): logging.warning("The buffer has to be saved " "before setting breakpoints") return breakableLines = getBreakpointLines("", self._qpart.text, True, False) if breakableLines is None: logging.warning("The breakable lines could not be identified " "due to the file compilation errors. Fix the code " "and try again.") return breakableLines = list(breakableLines) breakableLines.sort() if not breakableLines: logging.warning("There are no breakable lines") return if lineNo in breakableLines: self.__toggleBreakpoint(lineNo) return # There are breakable lines however the user requested a line which # is not breakable candidateLine = breakableLines[0] if lineNo < breakableLines[0]: candidateLine = breakableLines[0] elif lineNo > breakableLines[-1]: candidateLine = breakableLines[-1] else: lowerDistance = maxsize upperDistance = maxsize for breakableLine in breakableLines: if breakableLine < lineNo: lowerDistance = min(lowerDistance, lineNo - breakableLine) else: upperDistance = min(upperDistance, breakableLine - lineNo) if lowerDistance < upperDistance: candidateLine = lineNo - lowerDistance else: candidateLine = lineNo + upperDistance if not self._qpart.isLineOnScreen(candidateLine - 1): # The redirected breakpoint line is not on the screen, scroll it self._qpart.ensureLineOnScreen(candidateLine - 1) self._qpart.setFirstVisible(max(0, candidateLine - 2)) self.__toggleBreakpoint(candidateLine)