def setup_scene(self, img: Image): #if img.mode != "RGB": #img = img.convert("RGB") self.image = img scene = CanvasGraphicsScene() self.setScene(scene) #scene固有の初期化 qtimg = ImageQt(self.image) pixmap = QPixmap.fromImage(qtimg).copy() pixmap_item = QGraphicsPixmapItem(pixmap) self.scene().addItem(pixmap_item) pixmap_item.setPos(0, 0) self.rect_item = QGraphicsRectItem(0, 0, 200, 200) self.rect_item.setPen(QPen(QtCore.Qt.blue, 3)) self.rect_item.hide() self.scene().addItem(self.rect_item) self.frame_rect_item = QGraphicsRectItem(0, 0, self.image.width - 3, self.image.height - 3) self.frame_rect_item.setPen(QPen(QtCore.Qt.red, 5)) self.scene().addItem(self.frame_rect_item) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) img = self.image self.setSceneRect(0, 0, img.width, img.height) self.setFixedSize(img.width, img.height) self._dragging = False pass
def __init__(self, future_build_info, x=0, y=0, selectable=True): QGraphicsRectItem.__init__(self, x, y, self.WIDTH, self.WIDTH) self.future_build_info = future_build_info if selectable: self.setFlags(self.ItemIsSelectable | self.ItemIsFocusable) else: self.setFlags(self.ItemIsFocusable)
def __init__(self, parent=None): super(GameWindow, self).__init__(parent=parent) self.screen = None self.scene = QGraphicsScene() self.scene.setSceneRect( QRect(left=0, top=0, width=PLAYGROUND_SIZEX * SCALE_FACTORX, height=PLAYGROUND_SIZEY * SCALE_FACTORY)) self.setFrameStyle(4) self.setScene(self.scene) self.snake = [] # define SnakeHead self.snake.append(QGraphicsRectItem()) self.snake[0].setRect(QRect(0, 0, SCALE_FACTORX, SCALE_FACTORY)) self.snake[0].setBrush(brushHead) self.scene.addItem(self.snake[0]) # define rest of the snake for i in range(1, MAX_LENGTH_SNAKE): self.snake.append(QGraphicsRectItem()) self.snake[i].setRect(QRect(0, 0, SCALE_FACTORX, SCALE_FACTORY)) self.snake[i].setBrush(brushBody) self.snake[i].setVisible(False) self.scene.addItem(self.snake[i]) # Create the graphic item for apple self.goal = QGraphicsRectItem() self.goal.setRect(QRect(0, 0, SCALE_FACTORX, SCALE_FACTORY)) self.goal.setBrush(brushGoal) self.scene.addItem(self.goal) self.show()
def overlay_rect(self, color: int, x: int, y: int, w: int, h: int, timeout: int, line_width: int): pen = QPen(decode_color(color)) pen.setWidthF(max(1.0, line_width / 10)) gfx = QGraphicsRectItem(x, y, w, h) gfx.setPen(pen) self._finalize_gfx(gfx, timeout)
def __init__(self, *a, **kw): data = kw.pop("data") self.name = kw.pop("name") self.window = kw.pop("window") super().__init__(0, 0, 0, 0) self.setAcceptedMouseButtons(Qt.LeftButton) self.label = QGraphicsTextItem("", self) self.bottom_edge = QGraphicsRectItem(0, 0, 0, 0, self) self.bottom_edge.setBrush(QBrush("red", Qt.SolidPattern)) self.update_visuals(data)
def __init__(self): """Notification list graphics item. Used to show notifications for a ProjectItem """ super().__init__() self.bg = QGraphicsRectItem(self.boundingRect(), self) bg_brush = QApplication.palette().brush(QPalette.ToolTipBase) self.bg.setBrush(bg_brush) self.bg.setFlag(QGraphicsItem.ItemStacksBehindParent) self.setFlag(QGraphicsItem.ItemIsSelectable, enabled=False) self.setZValue(2)
def _compute_max_zoom(self): # The max zoom is the one that fits one item into the view # We don't allow to zoom any further than this item = QGraphicsRectItem(0, 0, ProjectItemIcon.ITEM_EXTENT, 0) self.scene().addItem(item) self.scene().removeItem(item) item_scene_rect = item.boundingRegion( item.sceneTransform()).boundingRect() item_view_rect = self.mapFromScene(item_scene_rect).boundingRect() viewport_extent = min(self.viewport().width(), self.viewport().height()) return viewport_extent / item_view_rect.width()
def setUp(self): horizontal_threshold = 1.0 vertical_threshold = 3.0 self.scene = ShrinkingScene(horizontal_threshold, vertical_threshold, None) item_size = 1.0 self.fixed_item = QGraphicsRectItem(0.0, 0.0, item_size, item_size) self.item = QGraphicsRectItem(0.0, 0.0, item_size, item_size) self.item.setPos(10.0, 10.0) self.scene.addItem(self.fixed_item) self.scene.addItem(self.item) self.assertEqual(self.scene.sceneRect(), QRectF(-0.5, -0.5, 12.0, 12.0))
def __init__(self, main_window, stage=1): super().__init__() self.main_window = main_window self.stage = stage self.upper_mask = QGraphicsRectItem(0, 0, content_width, 0) self.lower_mask = QGraphicsRectItem(0, content_height, content_width, 0) self.stage_text_item = QGraphicsTextItem() self.mask_height = 0 self.animation_timer_1 = QTimer() self.animation_timer_2 = QTimer() self.animation_timer_3 = QTimer() self.selected = None self.init()
def testIt(self): scene = QGraphicsScene() i1 = QGraphicsRectItem() scene.addItem(i1) i2 = QGraphicsRectItem(i1) i3 = QGraphicsRectItem() i4 = QGraphicsRectItem() group = scene.createItemGroup((i2, i3, i4)) scene.removeItem(i1) del i1 # this shouldn't delete i2 self.assertEqual(i2.scene(), scene) scene.destroyItemGroup(group) self.assertRaises(RuntimeError, group.type)
def __init__(self, x, y, width, height, text): """ A Rectangle with some text in it :param text: str :param x: float :param y: float :param height: float :param width: float """ self.id = LaunchButton.ID LaunchButton.ID += 1 print("my self.id = ", str(self.id)) self.x = x self.y = y self.width = width self.height = height self.text = text # super(SelectFolderButton, self).__init__(self.x, self.y, self.width, self.height) QObject.__init__(self) QGraphicsRectItem.__init__(self, self.x, self.y, self.width, self.height) self.setAcceptHoverEvents(True) # self.text = HText("Select Folder", self.x + self.width - 20, self.y + height / 2, self, 45) # self.text = HText("Select Folder", self.x + 5, self.y + 5, self, 45) # simple state array, represented as a numpy array, 0 = False, 1 = True # [0] = ZIPPED, [1] = SENT, [2] = SUBMITTED, [3] = FINISHED, [4] = DELIVERED self.state = np.zeros(5) self.state[0] = 1 print(self.state.any()) # indexes = np.array(np.where(self.state == 1)) # indexes = list(np.where(self.state == 1)) indexes = np.where(self.state == 1) print("TYPE") print(type(indexes)) # indexes.append(3) print("index state = ", indexes) print("len = ", len(indexes)) print("state = \n", self.state) self.mpen = scene_objects.initialize_qpen(QColor(7, 133, 192), width=2) # main block color self.current_color = QColor(7, 133, 192) # self.current_color_1 = Qt.gray # self.current_color_2 = Qt.gray self.i = 0 self.qdate_time = QDateTime() print("################################################################################\n")
def setUp(self): #Acquire resources super(ItemRetrieve, self).setUp() self.scene = QGraphicsScene() self.topleft = QGraphicsRectItem(0, 0, 100, 100) self.topright = QGraphicsRectItem(100, 0, 100, 100) self.bottomleft = QGraphicsRectItem(0, 100, 100, 100) self.bottomright = QGraphicsRectItem(100, 100, 100, 100) self.items = [self.topleft, self.topright, self.bottomleft, self.bottomright] for item in self.items: self.scene.addItem(item)
def draw_bounding_box(self): #self.item = QGraphicsPixmapItem(QPixmap(self.df["image"].iloc[self.index])) #self.scene.addItem(self.item) start = self.image.mapToScene(self.start) end = self.image.mapToScene(self.end) self.startSceneLoc = start self.endSceneLoc = end df = self.page_df scale = (1 / self.zoom) self.x1 = start.x() * scale #self.x3 = end.x()*scale #Fixed x length self.x3 = self.x1 + 250 * scale self.y1 = start.y() * scale self.y3 = end.y() * scale df = df[(df.x1 > self.x1) & (df.x3 < self.x3) & (df.y1 > self.y1) & (df.y3 < self.y3)] print(u"x1:", self.x1, u" x3:", self.x3, u" y1:", self.y1, u" y3:", self.y3, u" Scale:", scale) print(u"Current image:", self.report[self.page_index], u" Current df image:", df.image.unique()) print(df.word) self.bound_data_text = " ".join(df.word.to_list()) diff_x = (self.x1 - self.x3) * self.zoom diff_y = (self.y1 - self.y3) * self.zoom rectItem = QGraphicsRectItem(start.x(), start.y(), -diff_x, -diff_y) self.scene.addItem(rectItem) self.start = None self.end = None
def __init__(self, text=None, parent=None): super().__init__(parent) self._text = text or "" self._elided_text = text or "" self._elide_mode = Qt.ElideRight self._align_mode = Qt.AlignLeft self._max_width = None self._font = QFont() self._bounding_rect = QRectF() """Bounding and drawing rectangle. Determined automatically.""" self.background = QGraphicsRectItem(self) self.background.setPen(Qt.NoPen) self.background.setFlag(QGraphicsItem.ItemStacksBehindParent) self.adjust()
def drawBox(self): x1 = self.start.x() y1 = self.start.y() x3 = self.end.x() y3 = self.end.y() diff_x = x3 - x1 diff_y = y3 - y1 rectItem = QGraphicsRectItem(x1, y1, diff_x, diff_y) #rectItem.setBrush(QBrush(Qt.green)) self.scene.addItem(rectItem)
def __init__(self, entity_item): """Initializes item. Args: entity_item (spinetoolbox.widgets.graph_view_graphics_items.EntityItem): The parent item. """ super().__init__(entity_item) self.entity_item = entity_item self._font = QApplication.font() self._font.setPointSize(11) self.setFont(self._font) self.bg = QGraphicsRectItem(self) self.bg_color = QGuiApplication.palette().color( QPalette.Normal, QPalette.ToolTipBase) self.bg_color.setAlphaF(0.8) self.bg.setBrush(QBrush(self.bg_color)) self.bg.setPen(Qt.NoPen) self.bg.setFlag(QGraphicsItem.ItemStacksBehindParent) self.setFlag(QGraphicsItem.ItemIsSelectable, enabled=False) self.setAcceptHoverEvents(False)
def __init__(self, parent): """ Args: parent (ProjectItemIcon): the parent item """ super().__init__(parent) self._parent = parent rect_w = parent.rect().width() # Parent rect width self.text_margin = 0.05 * rect_w self.bg = QGraphicsRectItem(self.boundingRect(), self) bg_brush = QApplication.palette().brush(QPalette.ToolTipBase) self.bg.setBrush(bg_brush) self.bg.setFlag(QGraphicsItem.ItemStacksBehindParent) self.setFlag(QGraphicsItem.ItemIsSelectable, enabled=False) font = self.font() font.setPointSize(parent.text_font_size) font.setBold(True) self.setFont(font) doc = self.document() doc.setDocumentMargin(0)
def add_instance( self, instance: "GameInstance" ) -> Tuple[QGraphicsItem, Callable[[], None]]: """Add instance to manage, return a disconnect function and the canvas""" positionChanged = lambda rect: self.on_instance_moved(instance, rect) instance.positionChanged.connect(positionChanged) focusChanged = lambda focus: self.on_instance_focus_change( instance, focus) instance.focusChanged.connect(focusChanged) instance_pos = instance.get_position() gfx = QGraphicsRectItem(rect=instance_pos) gfx.setPen(self.transparent_pen) gfx.setPos(instance_pos.x(), instance_pos.y()) self.scene.addItem(gfx) self._instances[instance.wid] = gfx def disconnect(): gfx.hide() self.scene.removeItem(gfx) instance.positionChanged.disconnect(positionChanged) instance.focusChanged.disconnect(focusChanged) return gfx, disconnect
class GameWindow(QGraphicsView): def __init__(self, parent=None): super(GameWindow, self).__init__(parent=parent) self.screen = None self.scene = QGraphicsScene() self.scene.setSceneRect( QRect(left=0, top=0, width=PLAYGROUND_SIZEX * SCALE_FACTORX, height=PLAYGROUND_SIZEY * SCALE_FACTORY)) self.setFrameStyle(4) self.setScene(self.scene) self.snake = [] # define SnakeHead self.snake.append(QGraphicsRectItem()) self.snake[0].setRect(QRect(0, 0, SCALE_FACTORX, SCALE_FACTORY)) self.snake[0].setBrush(brushHead) self.scene.addItem(self.snake[0]) # define rest of the snake for i in range(1, MAX_LENGTH_SNAKE): self.snake.append(QGraphicsRectItem()) self.snake[i].setRect(QRect(0, 0, SCALE_FACTORX, SCALE_FACTORY)) self.snake[i].setBrush(brushBody) self.snake[i].setVisible(False) self.scene.addItem(self.snake[i]) # Create the graphic item for apple self.goal = QGraphicsRectItem() self.goal.setRect(QRect(0, 0, SCALE_FACTORX, SCALE_FACTORY)) self.goal.setBrush(brushGoal) self.scene.addItem(self.goal) self.show() def draw(self, state): self.goal.setPos(state.goal.x * SCALE_FACTORX, state.goal.y * SCALE_FACTORY) self.goal.setVisible(True) self.snake[0].setPos(float(state.snake[0].x * SCALE_FACTORX), float(state.snake[0].y * SCALE_FACTORY)) for i in range(1, state.snake_length): self.snake[i].setPos(state.snake[i].x * SCALE_FACTORX, state.snake[i].y * SCALE_FACTORY) self.snake[i].setVisible(True) for i in range(state.snake_length, MAX_LENGTH_SNAKE): self.snake[i].setVisible(False) def screenshot(self): self.screen = self.grab() self.screen.save("./snake_screen.png")
class ObjectLabelItem(QGraphicsTextItem): """Provides a label for ObjectItem's.""" entity_name_edited = Signal(str) def __init__(self, entity_item): """Initializes item. Args: entity_item (spinetoolbox.widgets.graph_view_graphics_items.EntityItem): The parent item. """ super().__init__(entity_item) self.entity_item = entity_item self._font = QApplication.font() self._font.setPointSize(11) self.setFont(self._font) self.bg = QGraphicsRectItem(self) self.bg_color = QGuiApplication.palette().color( QPalette.Normal, QPalette.ToolTipBase) self.bg_color.setAlphaF(0.8) self.bg.setBrush(QBrush(self.bg_color)) self.bg.setPen(Qt.NoPen) self.bg.setFlag(QGraphicsItem.ItemStacksBehindParent) self.setFlag(QGraphicsItem.ItemIsSelectable, enabled=False) self.setAcceptHoverEvents(False) self._cursor = self.textCursor() self._text_backup = None def setPlainText(self, text): """Set texts and resets position. Args: text (str) """ super().setPlainText(text) self.reset_position() def reset_position(self): """Adapts item geometry so text is always centered.""" rectf = self.boundingRect() x = -rectf.width() / 2 y = rectf.height() + 4 self.setPos(x, y) self.bg.setRect(self.boundingRect())
def __init__(self): QWidget.__init__(self) self.layout = QVBoxLayout(self) rect = QRectF(0, 0, 800, 800) self.scene = QGraphicsScene(rect) item = Node() self.scene.addItem(item) item1 = Node() item1.setPos(QPoint(50, 50)) self.scene.addItem(item1) item2 = QGraphicsRectItem(10, 10, 50, 50) self.scene.addItem(item2) line = Edge(item, item1) self.scene.addItem(line) self.view = NetworkView(self.scene, self) self.view.setCacheMode(QGraphicsView.CacheBackground) self.view.setViewportUpdateMode( QGraphicsView.BoundingRectViewportUpdate) print(item1.scenePos()) print(item1.pos()) self.layout.addWidget(self.view) self.setLayout(self.layout)
class TestShrinkingScene(unittest.TestCase): @classmethod def setUpClass(cls): if not QApplication.instance(): QApplication() def setUp(self): horizontal_threshold = 1.0 vertical_threshold = 3.0 self.scene = ShrinkingScene(horizontal_threshold, vertical_threshold, None) item_size = 1.0 self.fixed_item = QGraphicsRectItem(0.0, 0.0, item_size, item_size) self.item = QGraphicsRectItem(0.0, 0.0, item_size, item_size) self.item.setPos(10.0, 10.0) self.scene.addItem(self.fixed_item) self.scene.addItem(self.item) self.assertEqual(self.scene.sceneRect(), QRectF(-0.5, -0.5, 12.0, 12.0)) def test_shrink_if_needed_doesnt_shrink_within_thresholds(self): self.item.setPos(9.1, 7.1) self.scene.shrink_if_needed() self.assertEqual(self.scene.sceneRect(), QRectF(-0.5, -0.5, 12.0, 12.0)) def test_shrink_if_needed(self): self.item.setPos(8.9, 6.1) self.scene.shrink_if_needed() self.assertEqual(self.scene.sceneRect(), QRectF(-0.5, -0.5, 11.9, 11.1)) def test_shrink_if_needed_doesnt_shink_too_much(self): self.item.setPos(0.0, 0.0) self.scene.shrink_if_needed() self.assertEqual(self.scene.sceneRect(), QRectF(-0.5, -0.5, 3.0, 5.0))
def __init__(self, G): super().__init__() self.G = G # self.setMinimunSize(400, 400) self.scale(1, -1) # AXIS self.axis_center = QGraphicsRectItem(-100, -100, 200, 200) self.axis_center.setPen(QPen(QColor("black"))) self.axis_center.setBrush(QBrush(QColor("black"))) self.axis_center.setZValue(5000) self.axis_x = QGraphicsRectItem(0, 0, 1000, 30) self.axis_x.setPen(QPen(QColor("red"))) self.axis_x.setBrush(QBrush(QColor("red"))) self.axis_x.setZValue(5000) self.axis_y = QGraphicsRectItem(0, 0, 30, 1000) self.axis_y.setPen(QPen(QColor("blue"))) self.axis_y.setBrush(QBrush(QColor("blue"))) self.axis_y.setZValue(5000) self.set_draw_axis(True) self.draw_axis()
def _generate_hover_region(self): """ Paint the memory region indicator. """ if self._map_hover_region_item: self.scene().removeItem(self._map_hover_region_item) self._map_hover_region_item = None mr = self._map_hover_region if mr is None: return pw = 1.0 hpw = pw / 2 pen = QPen(Qt.red) pen.setWidth(pw) r = self._get_region_rect(mr) r = r.marginsRemoved(QMarginsF(hpw, hpw, hpw, hpw)) item = QGraphicsRectItem(r, parent=self) item.setPen(pen) item.setZValue(self.ZVALUE_HOVER) self._map_hover_region_item = item
def __init__(self, parent: QWidget = None) -> None: """ Create a GraphicsView for Facile. :param parent: The widget to embed the graphics view into :type parent: QWidget :return: None :rtype: NoneType """ super(FacileGraphicsView, self).__init__(parent) # set flags self.setDragMode(QGraphicsView.ScrollHandDrag) self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate) # show initial message scene = QGraphicsScene() box = QGraphicsRectItem(0, 0, 100, 100) box.setPen(QColor(Qt.transparent)) box.setBrush(QColor(Qt.transparent)) QGraphicsTextItem("Nothing to show here yet!", box) scene.addItem(box) self.setScene(scene)
class RankIcon(QGraphicsTextItem): def __init__(self, parent): """Rank icon graphics item. Used to show the rank of a ProjectItem within its DAG Args: parent (ProjectItemIcon): the parent item """ super().__init__(parent) self._parent = parent rect_w = parent.rect().width() # Parent rect width self.text_margin = 0.05 * rect_w self.bg = QGraphicsRectItem(self.boundingRect(), self) bg_brush = QApplication.palette().brush(QPalette.ToolTipBase) self.bg.setBrush(bg_brush) self.bg.setFlag(QGraphicsItem.ItemStacksBehindParent) self.setFlag(QGraphicsItem.ItemIsSelectable, enabled=False) font = self.font() font.setPointSize(parent.text_font_size) font.setBold(True) self.setFont(font) doc = self.document() doc.setDocumentMargin(0) def set_rank(self, rank): self.setPlainText(str(rank)) self.adjustSize() self.setTextWidth(self.text_margin + self.textWidth()) self.bg.setRect(self.boundingRect()) # Align center fmt = QTextBlockFormat() fmt.setAlignment(Qt.AlignHCenter) cursor = self.textCursor() cursor.select(QTextCursor.Document) cursor.mergeBlockFormat(fmt) cursor.clearSelection() self.setTextCursor(cursor)
QGraphicsRectItem, QWidget, QGraphicsSimpleTextItem, QGraphicsEllipseItem, QGraphicsPolygonItem, ) from PySide2.QtGui import (QPen, QBrush, QPolygonF) from PySide2.QtCore import (Qt, QRectF, QPoint, QPointF) import sys if __name__ == '__main__': app = QApplication(sys.argv) scene = QGraphicsScene(QRectF(-50, -50, 400, 200)) rect = QGraphicsRectItem(scene.sceneRect().adjusted(1, 1, -1, -1)) rect.setPen(QPen(Qt.red, 1)) scene.addItem(rect) rectItem = QGraphicsRectItem(QRectF(-25, 25, 200, 40)) rectItem.setPen(QPen(Qt.red, 3, Qt.DashDotLine)) rectItem.setBrush(Qt.gray) scene.addItem(rectItem) print(f'Rect Pos: {rectItem.pos()}') textItem = QGraphicsSimpleTextItem("Foundation of Qt") scene.addItem(textItem) print(f'Text Pos: {textItem.pos()}') textItem.setPos(50, 0) print(f'Text Pos: {textItem.pos()}')
class EntityLabelItem(QGraphicsTextItem): """Label item for items in GraphViewForm.""" entity_name_edited = Signal(str) def __init__(self, entity_item): """Initializes item. Args: entity_item (spinetoolbox.widgets.graph_view_graphics_items.EntityItem): The parent item. """ super().__init__(entity_item) self.entity_item = entity_item self._font = QApplication.font() self._font.setPointSize(11) self.setFont(self._font) self.bg = QGraphicsRectItem(self) color = QGuiApplication.palette().color(QPalette.Normal, QPalette.ToolTipBase) color.setAlphaF(0.8) self.set_bg_color(color) self.bg.setFlag(QGraphicsItem.ItemStacksBehindParent) self.setFlag(QGraphicsItem.ItemIsSelectable, enabled=False) self.setAcceptHoverEvents(False) self._cursor = self.textCursor() self._text_backup = None def setPlainText(self, text): """Set texts and resets position. Args: text (str) """ super().setPlainText(text) self.reset_position() def reset_position(self): """Adapts item geometry so text is always centered.""" rectf = self.boundingRect() x = -rectf.width() / 2 y = rectf.height() + 4 self.setPos(x, y) self.bg.setRect(self.boundingRect()) def set_bg_color(self, bg_color): """Sets background color. Args: bg_color (QColor) """ self.bg.setBrush(QBrush(bg_color)) def start_editing(self): """Starts editing.""" self.setTextInteractionFlags(Qt.TextEditorInteraction) self.setFocus() cursor = QTextCursor(self._cursor) cursor.select(QTextCursor.Document) self.setTextCursor(cursor) self._text_backup = self.toPlainText() def keyPressEvent(self, event): """Keeps text centered as the user types. Gives up focus when the user presses Enter or Return. Args: event (QKeyEvent) """ if event.key() in (Qt.Key_Return, Qt.Key_Enter): self.clearFocus() elif event.key() == Qt.Key_Escape: self.setPlainText(self._text_backup) self.clearFocus() else: super().keyPressEvent(event) self.reset_position() def focusOutEvent(self, event): """Ends editing and sends entity_name_edited signal.""" super().focusOutEvent(event) self.setTextInteractionFlags(Qt.NoTextInteraction) self.entity_name_edited.emit(self.toPlainText()) self.setTextCursor(self._cursor) def mouseDoubleClickEvent(self, event): """Starts editing the name. Args: event (QGraphicsSceneMouseEvent) """ self.start_editing()
class EntityItem(QGraphicsPixmapItem): def __init__(self, graph_view_form, x, y, extent, entity_id=None, entity_class_id=None): """Initializes item Args: graph_view_form (GraphViewForm): 'owner' x (float): x-coordinate of central point y (float): y-coordinate of central point extent (int): Preferred extent entity_id (int, optional): The entity id in case of a non-wip item entity_class_id (int, optional): The entity class id in case of a wip item """ if not entity_id and not entity_class_id: raise ValueError( "Can't create an RelationshipItem without relationship id nor relationship class id." ) super().__init__() self._graph_view_form = graph_view_form self.db_mngr = graph_view_form.db_mngr self.db_map = graph_view_form.db_map self.entity_id = entity_id self._entity_class_id = entity_class_id self._entity_name = f"<WIP {self.entity_class_name}>" self.arc_items = list() self._extent = extent self.refresh_icon() self.setPos(x, y) rect = self.boundingRect() self.setOffset(-rect.width() / 2, -rect.height() / 2) self._press_pos = None self._merge_target = None self._moved_on_scene = False self._view_transform = QTransform( ) # To determine collisions in the view self._views_cursor = {} self._bg = None self._bg_brush = Qt.NoBrush self._init_bg() self._bg.setFlag(QGraphicsItem.ItemStacksBehindParent, enabled=True) self.is_wip = None self._question_item = None # In case this becomes a template if not self.entity_id: self.become_wip() else: self.become_whole() self.setZValue(0) self.setFlag(QGraphicsItem.ItemIsSelectable, enabled=True) self.setFlag(QGraphicsItem.ItemIsMovable, enabled=True) self.setFlag(QGraphicsItem.ItemIgnoresTransformations, enabled=True) self.setFlag(QGraphicsItem.ItemSendsScenePositionChanges, enabled=True) self.setAcceptHoverEvents(True) self.setCursor(Qt.ArrowCursor) @property def entity_type(self): raise NotImplementedError() @property def entity_name(self): return self.db_mngr.get_item(self.db_map, self.entity_type, self.entity_id).get( "name", self._entity_name) @property def entity_class_type(self): return { "relationship": "relationship class", "object": "object class" }[self.entity_type] @property def entity_class_id(self): return self.db_mngr.get_item(self.db_map, self.entity_type, self.entity_id).get( "class_id", self._entity_class_id) @property def entity_class_name(self): return self.db_mngr.get_item(self.db_map, self.entity_class_type, self.entity_class_id)["name"] def boundingRect(self): return super().boundingRect() | self.childrenBoundingRect() def _init_bg(self): self._bg = QGraphicsRectItem(self.boundingRect(), self) self._bg.setPen(Qt.NoPen) def refresh_icon(self): """Refreshes the icon.""" pixmap = self.db_mngr.entity_class_icon( self.db_map, self.entity_class_type, self.entity_class_id).pixmap(self._extent) self.setPixmap(pixmap) def shape(self): """Returns a shape containing the entire bounding rect, to work better with icon transparency.""" path = QPainterPath() path.addRect(self.boundingRect()) return path def paint(self, painter, option, widget=None): """Shows or hides the selection halo.""" if option.state & (QStyle.State_Selected): self._paint_as_selected() option.state &= ~QStyle.State_Selected else: self._paint_as_deselected() super().paint(painter, option, widget) def _paint_as_selected(self): self._bg.setBrush(QGuiApplication.palette().highlight()) def _paint_as_deselected(self): self._bg.setBrush(self._bg_brush) def add_arc_item(self, arc_item): """Adds an item to the list of arcs. Args: arc_item (ArcItem) """ self.arc_items.append(arc_item) def become_wip(self): """Turns this item into a work-in-progress.""" self.is_wip = True font = QFont("", 0.6 * self._extent) self._question_item = OutlinedTextItem("?", self, font) # Position question item rect = super().boundingRect() question_rect = self._question_item.boundingRect() x = rect.center().x() - question_rect.width() / 2 y = rect.center().y() - question_rect.height() / 2 self._question_item.setPos(x, y) self.setToolTip(self._make_wip_tool_tip()) def _make_wip_tool_tip(self): raise NotImplementedError() def become_whole(self): """Removes the wip status from this item.""" self.is_wip = False if self._question_item: self.scene().removeItem(self._question_item) def adjust_to_zoom(self, transform): """Saves the view's transform to determine collisions later on. Args: transform (QTransform): The view's transformation matrix after the zoom. """ self._view_transform = transform factor = transform.m11() self.setFlag(QGraphicsItem.ItemIgnoresTransformations, enabled=factor > 1) def device_rect(self): """Returns the item's rect in devices's coordinates. Used to accurately determine collisions. """ return self.deviceTransform(self._view_transform).mapRect( super().boundingRect()) def _find_merge_target(self): """Returns a suitable merge target if any. Returns: spinetoolbox.widgets.graph_view_graphics_items.EntityItem, NoneType """ scene = self.scene() if not scene: return None colliding = [ x for x in scene.items() if isinstance(x, EntityItem) and x is not self and x.device_rect().intersects(self.device_rect()) ] return next(iter(colliding), None) # pylint: disable=no-self-use def _is_target_valid(self): """Whether or not the registered merge target is valid. Returns: bool """ return False # pylint: disable=no-self-use def merge_into_target(self, force=False): """Merges this item into the registered target if valid. Returns: bool: True if merged, False if not. """ return False def mousePressEvent(self, event): """Saves original position for bouncing purposes. Args: event (QGraphicsSceneMouseEvent) """ super().mousePressEvent(event) self._press_pos = self.pos() self._merge_target = None def mouseMoveEvent(self, event): """Moves the item and all connected arcs. Also checks for a merge target and sets an appropriate mouse cursor. Args: event (QGraphicsSceneMouseEvent) """ if event.buttons() & Qt.LeftButton == 0: super().mouseMoveEvent(event) return move_by = event.scenePos() - event.lastScenePos() # Move selected items together for item in self.scene().selectedItems(): if isinstance(item, (EntityItem)): item.moveBy(move_by.x(), move_by.y()) item.move_arc_items(move_by) self._merge_target = self._find_merge_target() for view in self.scene().views(): self._views_cursor.setdefault(view, view.viewport().cursor()) if not self._merge_target: try: view.viewport().setCursor(self._views_cursor[view]) except KeyError: pass continue if self._is_target_valid(): view.viewport().setCursor(Qt.DragCopyCursor) else: view.viewport().setCursor(Qt.ForbiddenCursor) def move_arc_items(self, pos_diff): """Moves arc items. Args: pos_diff (QPoint) """ raise NotImplementedError() def mouseReleaseEvent(self, event): """Merges the item into the registered target if any. Bounces it if not possible. Shrinks the scene if needed. Args: event (QGraphicsSceneMouseEvent) """ super().mouseReleaseEvent(event) if self._merge_target: if self.merge_into_target(): return self._bounce_back(self.pos()) if self._moved_on_scene: self._moved_on_scene = False scene = self.scene() scene.shrink_if_needed() scene.item_move_finished.emit(self) def _bounce_back(self, current_pos): """Bounces the item back from given position to its original position. Args: current_pos (QPoint) """ if self._press_pos is None: return self.move_arc_items(self._press_pos - current_pos) self.setPos(self._press_pos) def itemChange(self, change, value): """ Keeps track of item's movements on the scene. Args: change (GraphicsItemChange): a flag signalling the type of the change value: a value related to the change Returns: the same value given as input """ if change == QGraphicsItem.ItemScenePositionHasChanged: self._moved_on_scene = True return value def set_all_visible(self, on): """Sets visibility status for this item and all arc items. Args: on (bool) """ for item in self.arc_items: item.setVisible(on) self.setVisible(on) def wipe_out(self): """Removes this item and all its arc items from the scene.""" self.scene().removeItem(self) for arc_item in self.arc_items: if arc_item.scene(): arc_item.scene().removeItem(arc_item) other_item = arc_item.other_item(self) if other_item.is_wip: other_item.wipe_out() def contextMenuEvent(self, e): """Shows context menu. Args: e (QGraphicsSceneMouseEvent): Mouse event """ e.accept() if not self.isSelected() and not e.modifiers() & Qt.ControlModifier: self.scene().clearSelection() self.setSelected(True) self._show_item_context_menu_in_parent(e.screenPos()) def _show_item_context_menu_in_parent(self, pos): raise NotImplementedError()
def _init_bg(self): self._bg = QGraphicsRectItem(self.boundingRect(), self) self._bg.setPen(Qt.NoPen)
def __init__(self, x, y, w, h): QGraphicsRectItem.__init__(self, x, y, w, h)