def mousePressEvent(self, e): if self.supress: return self.last_press = self.itemAt(e.scenePos(), QTransform()) if self.selection: if (e.button()==qt.LeftButton and not self.itemAt(e.scenePos(), QTransform())) or e.button()==qt.RightButton: old_selection = self.selection self.selection = set() for it in old_selection: try: it.selected = False except AttributeError: pass if not self.itemAt(e.scenePos(), QTransform()): if e.button()==qt.LeftButton: if e.modifiers()&qt.ShiftModifier: self.selection_path_item = QGraphicsPathItem() self.selection_path = path = QPainterPath() self.selection_path_item.setPen(QPen(Color.selection, 0, qt.DashLine)) path.moveTo(e.scenePos()) self.selection_path_item.setPath(path) self.addItem(self.selection_path_item) if e.button()==qt.LeftButton or (self.use_rightclick and e.button()==qt.RightButton): if not e.modifiers()&qt.ShiftModifier: self.place(e.scenePos(), Cell.full if (e.button()==qt.LeftButton)^self.swap_buttons else Cell.empty) else: QGraphicsScene.mousePressEvent(self, e)
class Scene(common.Scene): def __init__(self): common.Scene.__init__(self) self.reset() self.swap_buttons = False self.use_rightclick = False self.ignore_release = False def reset(self): self.clear() self.preview = None self.selection = set() self.selection_path_item = None self.supress = False self.title = self.author = self.information = '' def place(self, p, kind=Cell.unknown): if not self.preview: self.preview = Cell() self.preview.kind = kind self.preview.setOpacity(0.4) self.addItem(self.preview) x, y = convert_pos(p.x(), p.y()) self.preview.setPos(x, y) self.preview.upd(False) self.preview.text = '' def mousePressEvent(self, e): if self.supress: return self.last_press = self.itemAt(e.scenePos(), QTransform()) if self.selection: if (e.button()==qt.LeftButton and not self.itemAt(e.scenePos(), QTransform())) or e.button()==qt.RightButton: old_selection = self.selection self.selection = set() for it in old_selection: try: it.selected = False except AttributeError: pass if not self.itemAt(e.scenePos(), QTransform()): if e.button()==qt.LeftButton: if e.modifiers()&qt.ShiftModifier: self.selection_path_item = QGraphicsPathItem() self.selection_path = path = QPainterPath() self.selection_path_item.setPen(QPen(Color.selection, 0, qt.DashLine)) path.moveTo(e.scenePos()) self.selection_path_item.setPath(path) self.addItem(self.selection_path_item) if e.button()==qt.LeftButton or (self.use_rightclick and e.button()==qt.RightButton): if not e.modifiers()&qt.ShiftModifier: self.place(e.scenePos(), Cell.full if (e.button()==qt.LeftButton)^self.swap_buttons else Cell.empty) else: QGraphicsScene.mousePressEvent(self, e) def mouseMoveEvent(self, e): if self.supress: return if self.selection_path_item: p = self.selection_path p.lineTo(e.scenePos()) p2 = QPainterPath(p) p2.lineTo(p.pointAtPercent(0)) self.selection_path_item.setPath(p2) elif self.preview: self.place(e.scenePos()) else: QGraphicsScene.mouseMoveEvent(self, e) def mouseReleaseEvent(self, e): if self.supress: return if self.selection_path_item: p = self.selection_path p.lineTo(p.pointAtPercent(0)) for it in self.items(p, qt.IntersectsItemShape): if isinstance(it, Cell): it.selected = True self.removeItem(self.selection_path_item) self.selection_path_item = None elif self.preview: col = None for it in self.collidingItems(self.preview): pass if isinstance(it, Column) and distance(it, self.preview)<1e-3: col = it continue if self.preview.overlaps(it, allow_horz=e.modifiers()&qt.AltModifier): with self.preview.upd_neighbors(): self.removeItem(self.preview) self.preview = None break else: self.preview.setOpacity(1) self.preview.show_info = self.black_show_info if self.preview.kind is Cell.empty else self.blue_show_info if col: if not self.itemAt(col.pos()-col.cell.pos()+self.preview.pos()): old_cell = col.cell col.cell = self.preview col.setPos(col.pos()-old_cell.pos()+self.preview.pos()) col.upd() else: with self.preview.upd_neighbors(): self.removeItem(self.preview) self.preview = None else: QGraphicsScene.mouseReleaseEvent(self, e) def mouseDoubleClickEvent(self, e): it = self.itemAt(e.scenePos(), QTransform()) if not it: self.mousePressEvent(e) return if not isinstance(it, Cell): return if self.last_press is None and not self.use_rightclick: if it.kind is Cell.full: it.kind = Cell.empty it.show_info = self.black_show_info else: it.kind = Cell.full it.show_info = self.blue_show_info self.ignore_release = True QGraphicsScene.mouseDoubleClickEvent(self, e)
class Scene(common.Scene): def __init__(self): common.Scene.__init__(self) self.reset() self.swap_buttons = False self.use_rightclick = False self.ignore_release = False self.undo_history_length = 16 self.undo_step() def reset(self): self.clear() self.preview = None self.selection = set() self.selection_path_item = None self.supress = False self.title = self.author = self.information = '' self.undo_history = [] self.undo_pos = -1 def _place(self, p, kind=Cell.unknown): if not self.preview: self.preview = Cell() self.preview.kind = kind self.preview.setOpacity(0.4) self.addItem(self.preview) x, y = convert_pos(p.x(), p.y()) x = round(x) for yy in [round(y), int(math.floor(y - 1e-4)), int(math.ceil(y + 1e-4))]: self.preview.coord = (x, yy) if not any(isinstance(it, Cell) for it in self.preview.overlapping): break else: self.preview.coord = (round(x), round(y)) self.preview.upd() self.preview._text.setText('') def mousePressEvent(self, e): if self.supress: return self.last_press = self.itemAt(e.scenePos(), QTransform()) if self.selection: if (e.button() == qt.LeftButton and not self.itemAt(e.scenePos(), QTransform())) or e.button() == qt.RightButton: old_selection = self.selection self.selection = set() for it in old_selection: try: it.selected = False except AttributeError: pass if not self.itemAt(e.scenePos(), QTransform()): if e.button() == qt.LeftButton: if e.modifiers() & qt.ShiftModifier: self.selection_path_item = QGraphicsPathItem() self.selection_path = path = QPainterPath() self.selection_path_item.setPen(QPen(Color.selection, 0, qt.DashLine)) path.moveTo(e.scenePos()) self.selection_path_item.setPath(path) self.addItem(self.selection_path_item) if e.button() == qt.LeftButton or (self.use_rightclick and e.button() == qt.RightButton): if not e.modifiers() & qt.ShiftModifier: self._place(e.scenePos(), Cell.full if (e.button() == qt.LeftButton) ^ self.swap_buttons else Cell.empty) else: common.Scene.mousePressEvent(self, e) def mouseMoveEvent(self, e): if self.supress: return if self.selection_path_item: p = self.selection_path p.lineTo(e.scenePos()) p2 = QPainterPath(p) p2.lineTo(p.pointAtPercent(0)) self.selection_path_item.setPath(p2) elif self.preview: self._place(e.scenePos()) else: common.Scene.mouseMoveEvent(self, e) def mouseReleaseEvent(self, e): if self.supress: return if self.selection_path_item: p = self.selection_path p.lineTo(p.pointAtPercent(0)) for it in self.items(p, qt.IntersectsItemShape): if isinstance(it, Cell): it.selected = True self.removeItem(self.selection_path_item) self.selection_path_item = None elif self.preview: col = None for it in self.preview.overlapping: if isinstance(it, Column): if it.coord == self.preview.coord: col = it continue if isinstance(it, Cell) or abs(it.coord.y - self.preview.coord.y) == 1: self.preview.remove() break else: if col: old_cell = col.cell p = (col.coord.x - old_cell.coord.x + self.preview.coord.x, col.coord.y - old_cell.coord.y + self.preview.coord.y) if not self.grid.get(p): old_cell = col.cell col.place((col.coord.x - old_cell.coord.x + self.preview.coord.x, col.coord.y - old_cell.coord.y + self.preview.coord.y)) col.upd() col = None if not col: self.preview.setOpacity(1) self.preview.place() self.undo_step() self.preview.show_info = self.black_show_info if self.preview.kind is Cell.empty else self.blue_show_info self.preview.upd(True) else: self.preview.remove() self.preview = None else: common.Scene.mouseReleaseEvent(self, e) def mouseDoubleClickEvent(self, e): it = self.itemAt(e.scenePos(), QTransform()) if not it: self.mousePressEvent(e) return if not isinstance(it, Cell): return if self.last_press is None and not self.use_rightclick: if it.kind is Cell.full: it.kind = Cell.empty it.show_info = self.black_show_info else: it.kind = Cell.full it.show_info = self.blue_show_info it.upd(True) self.ignore_release = True common.Scene.mouseDoubleClickEvent(self, e) def undo_step(self, it=None): step = dict(self.grid) if it is not None: new = type(it)() it.copyattrs(new) step[tuple(it.coord)] = new self.undo_history[self.undo_pos+1:] = [step] self.undo_pos = len(self.undo_history) - 1 if self.undo_history_length and len(self.undo_history) > self.undo_history_length: del self.undo_history[0] self.undo_pos -= 1 def undo(self, step=-1): self.undo_pos += step try: if self.undo_pos < 0: raise IndexError() grid = self.undo_history[self.undo_pos] except IndexError: self.undo_pos -= step return for it in self.items(): self.removeItem(it) self.grid = {} for (x, y), it in grid.items(): self.addItem(it) it.place((x, y)) self.full_upd() return True def redo(self): self.undo(1)