vibefpmgui.breakpoints_list
The Debug panel's list of breakpoints: every one in the project, each with its state drawn as in the editor's gutter (a red dot; hollow: disabled; grey: the debugger couldn't place it), its place and its line of code.
A click opens the line; the right-click menu enables, disables or removes one (and, from the Debug menu, all of them); Delete removes the selected one. Where the program stopped at a breakpoint, it's selected, and the gutter's yellow arrow is drawn over its dot. The code is in the editor's font and syntax colors.
1"""The Debug panel's list of breakpoints: every one in the project, each 2with its state drawn as in the editor's gutter (a red dot; hollow: disabled; 3grey: the debugger couldn't place it), its place and its line of code. 4 5A click opens the line; the right-click menu enables, disables or removes 6one (and, from the Debug menu, all of them); Delete removes the selected 7one. Where the program stopped at a breakpoint, it's selected, and the 8gutter's yellow arrow is drawn over its dot. The code is in the editor's 9font and syntax colors. 10""" 11 12from __future__ import annotations 13 14from collections.abc import Callable, Iterable 15from dataclasses import dataclass 16from pathlib import Path 17 18from pygments.styles import get_style_by_name 19from qtpy.QtCore import QPointF, QRectF, Qt, Signal 20from qtpy.QtGui import ( 21 QAction, 22 QColor, 23 QFont, 24 QIcon, 25 QPainter, 26 QPalette, 27 QPen, 28 QPixmap, 29 QPolygonF, 30) 31from qtpy.QtWidgets import ( 32 QAbstractItemView, 33 QApplication, 34 QHeaderView, 35 QMenu, 36 QStyle, 37 QStyledItemDelegate, 38 QStyleOptionViewItem, 39 QTreeWidget, 40 QTreeWidgetItem, 41) 42 43from . import highlighter as hl 44from .editor_shared import BREAKPOINT_COLOR, BREAKPOINT_UNPLACED, EXECUTION_COLOR 45from .result_tree import paint_code, syntax_formats 46 47ENABLED, DISABLED, UNPLACED = "enabled", "disabled", "unplaced" 48KEY_ROLE = Qt.UserRole # an item's (path, line) 49 50 51@dataclass(frozen=True) 52class BreakpointEntry: 53 path: str # (absolute: as the breakpoints are kept) 54 line: int 55 state: str # ENABLED, DISABLED or UNPLACED (enabled, but the debugger couldn't place it) 56 shown: str # its place as shown: the path in the project, and the line ("src/x.f90:12") 57 code: str = "" # the line's code (as in the file: its indentation not shown) 58 why: str = "" # why it wasn't placed 59 60 61_icons: dict[tuple[str, bool], QIcon] = {} 62 63 64def breakpoint_icon(state: str, here: bool = False) -> QIcon: 65 """The gutter's dot for a state; ``here``: the program is stopped at it 66 (the gutter's yellow arrow over the dot).""" 67 if (state, here) not in _icons: 68 icon = QIcon() 69 for ratio in (1, 2, 3): 70 pixmap = QPixmap(12 * ratio, 12 * ratio) 71 pixmap.setDevicePixelRatio(ratio) 72 pixmap.fill(Qt.transparent) 73 painter = QPainter(pixmap) 74 painter.setRenderHint(QPainter.Antialiasing) 75 if state == DISABLED: 76 painter.setPen(QPen(QColor(BREAKPOINT_COLOR), 1.5)) 77 painter.setBrush(Qt.NoBrush) 78 else: 79 painter.setPen(Qt.NoPen) 80 painter.setBrush(QColor(BREAKPOINT_UNPLACED if state == UNPLACED else BREAKPOINT_COLOR)) 81 painter.drawEllipse(QRectF(1.5, 1.5, 9, 9)) 82 if here: # (as editor_gutter draws it, in 12 pixels) 83 painter.setPen(QPen(QColor(EXECUTION_COLOR).darker(140), 1)) 84 painter.setBrush(QColor(EXECUTION_COLOR)) 85 painter.drawPolygon(QPolygonF([QPointF(0.5, 1.5), QPointF(5.5, 1.5), QPointF(11.5, 6), 86 QPointF(5.5, 10.5), QPointF(0.5, 10.5)])) 87 painter.end() 88 icon.addPixmap(pixmap) 89 _icons[(state, here)] = icon 90 return _icons[(state, here)] 91 92 93class _CodeDelegate(QStyledItemDelegate): 94 """The code column: the line in the editor's font and syntax colors 95 (plain on the selected row: its text color reads best there).""" 96 97 def __init__(self, tree: BreakpointsList): 98 super().__init__(tree) 99 self.tree = tree 100 101 def paint(self, painter, option, index): 102 opt = QStyleOptionViewItem(option) 103 self.initStyleOption(opt, index) 104 entry = self.tree.entry_at(index.row()) 105 if entry is None: 106 super().paint(painter, option, index) 107 return 108 opt.text = "" 109 style = opt.widget.style() if opt.widget else QApplication.style() 110 style.drawControl(QStyle.CE_ItemViewItem, opt, painter, opt.widget) 111 selected = bool(opt.state & QStyle.State_Selected) 112 group = QPalette.Active if opt.state & QStyle.State_Active else QPalette.Inactive 113 plain = opt.palette.color(group, QPalette.HighlightedText if selected else QPalette.Text) 114 if entry.state == DISABLED and not selected: 115 plain = opt.palette.color(group, QPalette.PlaceholderText) 116 code = entry.code.lstrip() 117 column = len(entry.code) - len(code) # (where the code shown starts in the line) 118 formats = None if selected or entry.state == DISABLED else self.tree.line_formats(entry) 119 painter.save() 120 painter.setClipRect(opt.rect) 121 paint_code(painter, opt.rect.adjusted(4, 0, 0, 0), code, formats, column, self.tree.mono, plain) 122 painter.restore() 123 124 125def state_text(entry: BreakpointEntry) -> str: 126 if entry.state == DISABLED: 127 return "Disabled: the debugger doesn't stop here" 128 if entry.state == UNPLACED: 129 return f"Not placed: {entry.why}" if entry.why else "Not placed by the debugger" 130 return "Enabled" 131 132 133class BreakpointsList(QTreeWidget): 134 open_requested = Signal(str, int) # path, line: a breakpoint clicked 135 enabled_toggled = Signal(str, int) # path, line: enable it if disabled, else disable it 136 remove_requested = Signal(str, int) # path, line 137 138 def __init__(self, more_actions: Iterable[QAction] = (), parent=None): 139 """``more_actions``: added to every right-click menu (the Debug menu's 140 Disable All and Remove All).""" 141 super().__init__(parent) 142 self.more_actions = list(more_actions) 143 self.entries: list[BreakpointEntry] = [] 144 self.setHeaderLabels(["Breakpoint", "Code"]) 145 self.setRootIsDecorated(False) 146 self.setUniformRowHeights(True) 147 self.setSelectionMode(QAbstractItemView.SingleSelection) 148 self.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) # (the code: the rest) 149 self.setContextMenuPolicy(Qt.CustomContextMenu) 150 self.customContextMenuRequested.connect(self._menu_at) 151 self.itemClicked.connect(self._open) 152 self.itemActivated.connect(self._open) # (Enter, a double-click) 153 self._hit: tuple[str, int] | None = None # where the program stopped (selected, the arrow on it) 154 self.mono = QFont() # the code's font: the editor's (set by the window) 155 self.lines_for: Callable[[str], list[str]] | None = None # a file's lines (set by the window) 156 self._style = get_style_by_name(hl.style_name(QApplication.palette())) 157 self._formats: dict = {} # token type -> format 158 self._line_formats: dict[tuple[str, int, str], list | None] = {} 159 self.setItemDelegateForColumn(1, _CodeDelegate(self)) 160 161 # ------------------------------------------------------------ contents 162 def set_entries(self, entries: list[BreakpointEntry]): 163 """The breakpoints now (the selection kept, if its breakpoint still is).""" 164 if entries == self.entries: 165 return 166 current = self.current_key() 167 self.entries = list(entries) 168 self._line_formats.clear() 169 self.clear() 170 for entry in entries: 171 item = QTreeWidgetItem([entry.shown, entry.code.strip()]) 172 item.setIcon(0, breakpoint_icon(entry.state, (entry.path, entry.line) == self._hit)) 173 item.setData(0, KEY_ROLE, (entry.path, entry.line)) 174 tip = f"{entry.path}:{entry.line}\n{state_text(entry)}" 175 item.setToolTip(0, tip) 176 item.setToolTip(1, tip) 177 if entry.state == DISABLED: 178 item.setForeground(0, self.palette().placeholderText()) 179 item.setForeground(1, self.palette().placeholderText()) 180 self.addTopLevelItem(item) 181 self._select(self._hit or current) 182 183 def entry_at(self, row: int) -> BreakpointEntry | None: 184 item = self.topLevelItem(row) 185 if item is None: 186 return None 187 key = tuple(item.data(0, KEY_ROLE)) 188 return next((e for e in self.entries if (e.path, e.line) == key), None) 189 190 def line_formats(self, entry: BreakpointEntry) -> list | None: 191 """The syntax format of each column of a breakpoint's line (None: plain).""" 192 key = (entry.path, entry.line, entry.code) 193 if key not in self._line_formats: 194 lines = self.lines_for(entry.path) if self.lines_for is not None else [entry.code] 195 line = entry.line if self.lines_for is not None else 1 196 self._line_formats[key] = syntax_formats(lines, line, Path(entry.path), self._style, self._formats) 197 return self._line_formats[key] 198 199 def refresh_style(self): 200 """The editor's syntax colors (View → Syntax Colors; light or dark).""" 201 self._style = get_style_by_name(hl.style_name(QApplication.palette())) 202 self._formats.clear() 203 self._line_formats.clear() 204 self.viewport().update() 205 206 def item_for(self, path: str, line: int) -> QTreeWidgetItem | None: 207 for i in range(self.topLevelItemCount()): 208 item = self.topLevelItem(i) 209 if tuple(item.data(0, KEY_ROLE)) == (path, line): 210 return item 211 return None 212 213 def current_key(self) -> tuple[str, int] | None: 214 item = self.currentItem() 215 return tuple(item.data(0, KEY_ROLE)) if item is not None and item.isSelected() else None 216 217 def show_hit(self, where: tuple[str, int] | None): 218 """The breakpoint the program stopped at, selected (None: it's not 219 stopped at one: nothing selected).""" 220 for entry in self.entries: # (the arrow: off the one it was on, onto this one) 221 if (entry.path, entry.line) in (self._hit, where): 222 self.item_for(entry.path, entry.line).setIcon( 223 0, breakpoint_icon(entry.state, (entry.path, entry.line) == where)) 224 self._hit = where 225 self._select(where) 226 227 def _select(self, key: tuple[str, int] | None): 228 item = self.item_for(*key) if key else None 229 if item is None: 230 self.clearSelection() 231 self.setCurrentItem(None) 232 return 233 self.setCurrentItem(item) 234 item.setSelected(True) 235 self.scrollToItem(item) 236 237 # ------------------------------------------------------------ using it 238 def _open(self, item: QTreeWidgetItem, _column: int = 0): 239 path, line = item.data(0, KEY_ROLE) 240 self.open_requested.emit(path, line) 241 242 def menu_for(self, item: QTreeWidgetItem | None) -> QMenu: 243 menu = QMenu(self) 244 if item is not None: 245 path, line = item.data(0, KEY_ROLE) 246 entry = next(e for e in self.entries if (e.path, e.line) == (path, line)) 247 menu.addAction("Go to Line", lambda: self.open_requested.emit(path, line)) 248 menu.addAction("Enable Breakpoint" if entry.state == DISABLED else "Disable Breakpoint", 249 lambda: self.enabled_toggled.emit(path, line)) 250 menu.addAction("Remove Breakpoint", lambda: self.remove_requested.emit(path, line)) 251 if self.more_actions: 252 menu.addSeparator() 253 menu.addActions(self.more_actions) 254 return menu 255 256 def _menu_at(self, pos): 257 item = self.itemAt(pos) 258 if item is None and not self.entries: 259 return 260 menu = self.menu_for(item) 261 menu.exec(self.viewport().mapToGlobal(pos)) 262 menu.deleteLater() 263 264 def keyPressEvent(self, event): 265 key = self.current_key() 266 if event.key() in (Qt.Key_Delete, Qt.Key_Backspace) and key is not None: 267 self.remove_requested.emit(*key) 268 return 269 super().keyPressEvent(event)
52@dataclass(frozen=True) 53class BreakpointEntry: 54 path: str # (absolute: as the breakpoints are kept) 55 line: int 56 state: str # ENABLED, DISABLED or UNPLACED (enabled, but the debugger couldn't place it) 57 shown: str # its place as shown: the path in the project, and the line ("src/x.f90:12") 58 code: str = "" # the line's code (as in the file: its indentation not shown) 59 why: str = "" # why it wasn't placed
65def breakpoint_icon(state: str, here: bool = False) -> QIcon: 66 """The gutter's dot for a state; ``here``: the program is stopped at it 67 (the gutter's yellow arrow over the dot).""" 68 if (state, here) not in _icons: 69 icon = QIcon() 70 for ratio in (1, 2, 3): 71 pixmap = QPixmap(12 * ratio, 12 * ratio) 72 pixmap.setDevicePixelRatio(ratio) 73 pixmap.fill(Qt.transparent) 74 painter = QPainter(pixmap) 75 painter.setRenderHint(QPainter.Antialiasing) 76 if state == DISABLED: 77 painter.setPen(QPen(QColor(BREAKPOINT_COLOR), 1.5)) 78 painter.setBrush(Qt.NoBrush) 79 else: 80 painter.setPen(Qt.NoPen) 81 painter.setBrush(QColor(BREAKPOINT_UNPLACED if state == UNPLACED else BREAKPOINT_COLOR)) 82 painter.drawEllipse(QRectF(1.5, 1.5, 9, 9)) 83 if here: # (as editor_gutter draws it, in 12 pixels) 84 painter.setPen(QPen(QColor(EXECUTION_COLOR).darker(140), 1)) 85 painter.setBrush(QColor(EXECUTION_COLOR)) 86 painter.drawPolygon(QPolygonF([QPointF(0.5, 1.5), QPointF(5.5, 1.5), QPointF(11.5, 6), 87 QPointF(5.5, 10.5), QPointF(0.5, 10.5)])) 88 painter.end() 89 icon.addPixmap(pixmap) 90 _icons[(state, here)] = icon 91 return _icons[(state, here)]
The gutter's dot for a state; here: the program is stopped at it
(the gutter's yellow arrow over the dot).
134class BreakpointsList(QTreeWidget): 135 open_requested = Signal(str, int) # path, line: a breakpoint clicked 136 enabled_toggled = Signal(str, int) # path, line: enable it if disabled, else disable it 137 remove_requested = Signal(str, int) # path, line 138 139 def __init__(self, more_actions: Iterable[QAction] = (), parent=None): 140 """``more_actions``: added to every right-click menu (the Debug menu's 141 Disable All and Remove All).""" 142 super().__init__(parent) 143 self.more_actions = list(more_actions) 144 self.entries: list[BreakpointEntry] = [] 145 self.setHeaderLabels(["Breakpoint", "Code"]) 146 self.setRootIsDecorated(False) 147 self.setUniformRowHeights(True) 148 self.setSelectionMode(QAbstractItemView.SingleSelection) 149 self.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) # (the code: the rest) 150 self.setContextMenuPolicy(Qt.CustomContextMenu) 151 self.customContextMenuRequested.connect(self._menu_at) 152 self.itemClicked.connect(self._open) 153 self.itemActivated.connect(self._open) # (Enter, a double-click) 154 self._hit: tuple[str, int] | None = None # where the program stopped (selected, the arrow on it) 155 self.mono = QFont() # the code's font: the editor's (set by the window) 156 self.lines_for: Callable[[str], list[str]] | None = None # a file's lines (set by the window) 157 self._style = get_style_by_name(hl.style_name(QApplication.palette())) 158 self._formats: dict = {} # token type -> format 159 self._line_formats: dict[tuple[str, int, str], list | None] = {} 160 self.setItemDelegateForColumn(1, _CodeDelegate(self)) 161 162 # ------------------------------------------------------------ contents 163 def set_entries(self, entries: list[BreakpointEntry]): 164 """The breakpoints now (the selection kept, if its breakpoint still is).""" 165 if entries == self.entries: 166 return 167 current = self.current_key() 168 self.entries = list(entries) 169 self._line_formats.clear() 170 self.clear() 171 for entry in entries: 172 item = QTreeWidgetItem([entry.shown, entry.code.strip()]) 173 item.setIcon(0, breakpoint_icon(entry.state, (entry.path, entry.line) == self._hit)) 174 item.setData(0, KEY_ROLE, (entry.path, entry.line)) 175 tip = f"{entry.path}:{entry.line}\n{state_text(entry)}" 176 item.setToolTip(0, tip) 177 item.setToolTip(1, tip) 178 if entry.state == DISABLED: 179 item.setForeground(0, self.palette().placeholderText()) 180 item.setForeground(1, self.palette().placeholderText()) 181 self.addTopLevelItem(item) 182 self._select(self._hit or current) 183 184 def entry_at(self, row: int) -> BreakpointEntry | None: 185 item = self.topLevelItem(row) 186 if item is None: 187 return None 188 key = tuple(item.data(0, KEY_ROLE)) 189 return next((e for e in self.entries if (e.path, e.line) == key), None) 190 191 def line_formats(self, entry: BreakpointEntry) -> list | None: 192 """The syntax format of each column of a breakpoint's line (None: plain).""" 193 key = (entry.path, entry.line, entry.code) 194 if key not in self._line_formats: 195 lines = self.lines_for(entry.path) if self.lines_for is not None else [entry.code] 196 line = entry.line if self.lines_for is not None else 1 197 self._line_formats[key] = syntax_formats(lines, line, Path(entry.path), self._style, self._formats) 198 return self._line_formats[key] 199 200 def refresh_style(self): 201 """The editor's syntax colors (View → Syntax Colors; light or dark).""" 202 self._style = get_style_by_name(hl.style_name(QApplication.palette())) 203 self._formats.clear() 204 self._line_formats.clear() 205 self.viewport().update() 206 207 def item_for(self, path: str, line: int) -> QTreeWidgetItem | None: 208 for i in range(self.topLevelItemCount()): 209 item = self.topLevelItem(i) 210 if tuple(item.data(0, KEY_ROLE)) == (path, line): 211 return item 212 return None 213 214 def current_key(self) -> tuple[str, int] | None: 215 item = self.currentItem() 216 return tuple(item.data(0, KEY_ROLE)) if item is not None and item.isSelected() else None 217 218 def show_hit(self, where: tuple[str, int] | None): 219 """The breakpoint the program stopped at, selected (None: it's not 220 stopped at one: nothing selected).""" 221 for entry in self.entries: # (the arrow: off the one it was on, onto this one) 222 if (entry.path, entry.line) in (self._hit, where): 223 self.item_for(entry.path, entry.line).setIcon( 224 0, breakpoint_icon(entry.state, (entry.path, entry.line) == where)) 225 self._hit = where 226 self._select(where) 227 228 def _select(self, key: tuple[str, int] | None): 229 item = self.item_for(*key) if key else None 230 if item is None: 231 self.clearSelection() 232 self.setCurrentItem(None) 233 return 234 self.setCurrentItem(item) 235 item.setSelected(True) 236 self.scrollToItem(item) 237 238 # ------------------------------------------------------------ using it 239 def _open(self, item: QTreeWidgetItem, _column: int = 0): 240 path, line = item.data(0, KEY_ROLE) 241 self.open_requested.emit(path, line) 242 243 def menu_for(self, item: QTreeWidgetItem | None) -> QMenu: 244 menu = QMenu(self) 245 if item is not None: 246 path, line = item.data(0, KEY_ROLE) 247 entry = next(e for e in self.entries if (e.path, e.line) == (path, line)) 248 menu.addAction("Go to Line", lambda: self.open_requested.emit(path, line)) 249 menu.addAction("Enable Breakpoint" if entry.state == DISABLED else "Disable Breakpoint", 250 lambda: self.enabled_toggled.emit(path, line)) 251 menu.addAction("Remove Breakpoint", lambda: self.remove_requested.emit(path, line)) 252 if self.more_actions: 253 menu.addSeparator() 254 menu.addActions(self.more_actions) 255 return menu 256 257 def _menu_at(self, pos): 258 item = self.itemAt(pos) 259 if item is None and not self.entries: 260 return 261 menu = self.menu_for(item) 262 menu.exec(self.viewport().mapToGlobal(pos)) 263 menu.deleteLater() 264 265 def keyPressEvent(self, event): 266 key = self.current_key() 267 if event.key() in (Qt.Key_Delete, Qt.Key_Backspace) and key is not None: 268 self.remove_requested.emit(*key) 269 return 270 super().keyPressEvent(event)
QTreeWidget(self, /, parent: PySide6.QtWidgets.QWidget | None = None, *, columnCount: int | None = None, topLevelItemCount: int | None = None, supportedDragActions: PySide6.QtCore.Qt.DropAction | None = None) -> None
139 def __init__(self, more_actions: Iterable[QAction] = (), parent=None): 140 """``more_actions``: added to every right-click menu (the Debug menu's 141 Disable All and Remove All).""" 142 super().__init__(parent) 143 self.more_actions = list(more_actions) 144 self.entries: list[BreakpointEntry] = [] 145 self.setHeaderLabels(["Breakpoint", "Code"]) 146 self.setRootIsDecorated(False) 147 self.setUniformRowHeights(True) 148 self.setSelectionMode(QAbstractItemView.SingleSelection) 149 self.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) # (the code: the rest) 150 self.setContextMenuPolicy(Qt.CustomContextMenu) 151 self.customContextMenuRequested.connect(self._menu_at) 152 self.itemClicked.connect(self._open) 153 self.itemActivated.connect(self._open) # (Enter, a double-click) 154 self._hit: tuple[str, int] | None = None # where the program stopped (selected, the arrow on it) 155 self.mono = QFont() # the code's font: the editor's (set by the window) 156 self.lines_for: Callable[[str], list[str]] | None = None # a file's lines (set by the window) 157 self._style = get_style_by_name(hl.style_name(QApplication.palette())) 158 self._formats: dict = {} # token type -> format 159 self._line_formats: dict[tuple[str, int, str], list | None] = {} 160 self.setItemDelegateForColumn(1, _CodeDelegate(self))
more_actions: added to every right-click menu (the Debug menu's
Disable All and Remove All).
163 def set_entries(self, entries: list[BreakpointEntry]): 164 """The breakpoints now (the selection kept, if its breakpoint still is).""" 165 if entries == self.entries: 166 return 167 current = self.current_key() 168 self.entries = list(entries) 169 self._line_formats.clear() 170 self.clear() 171 for entry in entries: 172 item = QTreeWidgetItem([entry.shown, entry.code.strip()]) 173 item.setIcon(0, breakpoint_icon(entry.state, (entry.path, entry.line) == self._hit)) 174 item.setData(0, KEY_ROLE, (entry.path, entry.line)) 175 tip = f"{entry.path}:{entry.line}\n{state_text(entry)}" 176 item.setToolTip(0, tip) 177 item.setToolTip(1, tip) 178 if entry.state == DISABLED: 179 item.setForeground(0, self.palette().placeholderText()) 180 item.setForeground(1, self.palette().placeholderText()) 181 self.addTopLevelItem(item) 182 self._select(self._hit or current)
The breakpoints now (the selection kept, if its breakpoint still is).
191 def line_formats(self, entry: BreakpointEntry) -> list | None: 192 """The syntax format of each column of a breakpoint's line (None: plain).""" 193 key = (entry.path, entry.line, entry.code) 194 if key not in self._line_formats: 195 lines = self.lines_for(entry.path) if self.lines_for is not None else [entry.code] 196 line = entry.line if self.lines_for is not None else 1 197 self._line_formats[key] = syntax_formats(lines, line, Path(entry.path), self._style, self._formats) 198 return self._line_formats[key]
The syntax format of each column of a breakpoint's line (None: plain).
200 def refresh_style(self): 201 """The editor's syntax colors (View → Syntax Colors; light or dark).""" 202 self._style = get_style_by_name(hl.style_name(QApplication.palette())) 203 self._formats.clear() 204 self._line_formats.clear() 205 self.viewport().update()
The editor's syntax colors (View → Syntax Colors; light or dark).
218 def show_hit(self, where: tuple[str, int] | None): 219 """The breakpoint the program stopped at, selected (None: it's not 220 stopped at one: nothing selected).""" 221 for entry in self.entries: # (the arrow: off the one it was on, onto this one) 222 if (entry.path, entry.line) in (self._hit, where): 223 self.item_for(entry.path, entry.line).setIcon( 224 0, breakpoint_icon(entry.state, (entry.path, entry.line) == where)) 225 self._hit = where 226 self._select(where)
The breakpoint the program stopped at, selected (None: it's not stopped at one: nothing selected).
265 def keyPressEvent(self, event): 266 key = self.current_key() 267 if event.key() in (Qt.Key_Delete, Qt.Key_Backspace) and key is not None: 268 self.remove_requested.emit(*key) 269 return 270 super().keyPressEvent(event)
keyPressEvent(self, event: PySide6.QtGui.QKeyEvent, /) -> None