/tmp/snapshot-pyside-6.2/tqtc-pyside-setup/examples/widgets/graphicsview/diagramscene

(You can also check this code in the repository)

<!DOCTYPE RCC><RCC version="1.0">
<qresource>
    <file>images/pointer.png</file>
    <file>images/linepointer.png</file>
    <file>images/textpointer.png</file>
    <file>images/bold.png</file>
    <file>images/italic.png</file>
    <file>images/underline.png</file>
    <file>images/floodfill.png</file>
    <file>images/bringtofront.png</file>
    <file>images/delete.png</file>
    <file>images/sendtoback.png</file>
    <file>images/linecolor.png</file>
    <file>images/background1.png</file>
    <file>images/background2.png</file>
    <file>images/background3.png</file>
    <file>images/background4.png</file>
</qresource>
</RCC>
import math
import sys

from PySide6.QtCore import (QLineF, QPointF, QRect, QRectF, QSize, QSizeF, Qt,
                            Signal)
from PySide6.QtGui import (QAction, QColor, QFont, QIcon, QIntValidator,
                           QPainter, QPainterPath, QPen, QPixmap, QPolygonF)
from PySide6.QtWidgets import (QApplication, QButtonGroup, QComboBox,
                               QFontComboBox, QGraphicsAnchorLayout,
                               QGraphicsItem, QGraphicsLineItem,
                               QGraphicsPolygonItem, QGraphicsTextItem,
                               QGraphicsScene, QGraphicsView, QGridLayout,
                               QHBoxLayout, QLabel, QMainWindow, QMenu,
                               QMessageBox, QSizePolicy, QToolBox, QToolButton,
                               QWidget)

import diagramscene_rc


class Arrow(QGraphicsLineItem):
    def __init__(self, startItem, endItem, parent=None, scene=None):
        super().__init__(parent, scene)

        self._arrow_head = QPolygonF()

        self._my_start_item = startItem
        self._my_end_item = endItem
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
        self._my_color = Qt.black
        self.setPen(QPen(self._my_color, 2, Qt.SolidLine,
                Qt.RoundCap, Qt.RoundJoin))

    def set_color(self, color):
        self._my_color = color

    def start_item(self):
        return self._my_start_item

    def end_item(self):
        return self._my_end_item

    def boundingRect(self):
        extra = (self.pen().width() + 20) / 2.0
        p1 = self.line().p1()
        p2 = self.line().p2()
        rect = QRectF(p1, QSizeF(p2.x() - p1.x(), p2.y() - p1.y()))
        return rect.normalized().adjusted(-extra, -extra, extra, extra)

    def shape(self):
        path = super(Arrow, self).shape()
        path.addPolygon(self._arrow_head)
        return path

    def update_position(self):
        start = self.mapFromItem(self._my_start_item, 0, 0)
        end = self.mapFromItem(self._my_end_item, 0, 0)
        self.setLine(QLineF(start, end))

    def paint(self, painter, option, widget=None):
        if (self._my_start_item.collidesWithItem(self._my_end_item)):
            return

        my_start_item = self._my_start_item
        my_end_item = self._my_end_item
        my_color = self._my_color
        my_pen = self.pen()
        my_pen.setColor(self._my_color)
        arrow_size = 20.0
        painter.setPen(my_pen)
        painter.setBrush(self._my_color)

        center_line = QLineF(my_start_item.pos(), my_end_item.pos())
        end_polygon = my_end_item.polygon()
        p1 = end_polygon.at(0) + my_end_item.pos()

        intersect_point = QPointF()
        for i in end_polygon:
            p2 = i + my_end_item.pos()
            poly_line = QLineF(p1, p2)
            intersectType, intersect_point = poly_line.intersects(center_line)
            if intersectType == QLineF.BoundedIntersection:
                break
            p1 = p2

        self.setLine(QLineF(intersect_point, my_start_item.pos()))
        line = self.line()

        angle = math.acos(line.dx() / line.length())
        if line.dy() >= 0:
            angle = (math.pi * 2.0) - angle

        arrow_head1 = QPointF(math.sin(angle + math.pi / 3.0) * arrow_size,
                              math.cos(angle + math.pi / 3) * arrow_size)
        arrow_p1 = line.p1() + arrow_head1
        arrow_head2 = QPointF(math.sin(angle + math.pi - math.pi / 3.0) * arrow_size,
                              math.cos(angle + math.pi - math.pi / 3.0) * arrow_size)
        arrow_p2 = line.p1() + arrow_head2

        self._arrow_head.clear()
        for point in [line.p1(), arrow_p1, arrow_p2]:
            self._arrow_head.append(point)

        painter.drawLine(line)
        painter.drawPolygon(self._arrow_head)
        if self.isSelected():
            painter.setPen(QPen(my_color, 1, Qt.DashLine))
            my_line = QLineF(line)
            my_line.translate(0, 4.0)
            painter.drawLine(my_line)
            my_line.translate(0, -8.0)
            painter.drawLine(my_line)


class DiagramTextItem(QGraphicsTextItem):
    lost_focus = Signal(QGraphicsTextItem)

    selected_change = Signal(QGraphicsItem)

    def __init__(self, parent=None, scene=None):
        super().__init__(parent, scene)

        self.setFlag(QGraphicsItem.ItemIsMovable)
        self.setFlag(QGraphicsItem.ItemIsSelectable)

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemSelectedChange:
            self.selected_change.emit(self)
        return value

    def focusOutEvent(self, event):
        self.setTextInteractionFlags(Qt.NoTextInteraction)
        self.lost_focus.emit(self)
        super(DiagramTextItem, self).focusOutEvent(event)

    def mouseDoubleClickEvent(self, event):
        if self.textInteractionFlags() == Qt.NoTextInteraction:
            self.setTextInteractionFlags(Qt.TextEditorInteraction)
        super(DiagramTextItem, self).mouseDoubleClickEvent(event)


class DiagramItem(QGraphicsPolygonItem):
    Step, Conditional, StartEnd, Io = range(4)

    def __init__(self, diagram_type, contextMenu, parent=None, scene=None):
        super().__init__(parent, scene)

        self.arrows = []

        self.diagram_type = diagram_type
        self._my_context_menu = contextMenu

        path = QPainterPath()
        if self.diagram_type == self.StartEnd:
            path.moveTo(200, 50)
            path.arcTo(150, 0, 50, 50, 0, 90)
            path.arcTo(50, 0, 50, 50, 90, 90)
            path.arcTo(50, 50, 50, 50, 180, 90)
            path.arcTo(150, 50, 50, 50, 270, 90)
            path.lineTo(200, 25)
            self._my_polygon = path.toFillPolygon()
        elif self.diagram_type == self.Conditional:
            self._my_polygon = QPolygonF([
                    QPointF(-100, 0), QPointF(0, 100),
                    QPointF(100, 0), QPointF(0, -100),
                    QPointF(-100, 0)])
        elif self.diagram_type == self.Step:
            self._my_polygon = QPolygonF([
                    QPointF(-100, -100), QPointF(100, -100),
                    QPointF(100, 100), QPointF(-100, 100),
                    QPointF(-100, -100)])
        else:
            self._my_polygon = QPolygonF([
                    QPointF(-120, -80), QPointF(-70, 80),
                    QPointF(120, 80), QPointF(70, -80),
                    QPointF(-120, -80)])

        self.setPolygon(self._my_polygon)
        self.setFlag(QGraphicsItem.ItemIsMovable, True)
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)

    def remove_arrow(self, arrow):
        try:
            self.arrows.remove(arrow)
        except ValueError:
            pass

    def remove_arrows(self):
        for arrow in self.arrows[:]:
            arrow.start_item().remove_arrow(arrow)
            arrow.end_item().remove_arrow(arrow)
            self.scene().removeItem(arrow)

    def add_arrow(self, arrow):
        self.arrows.append(arrow)

    def image(self):
        pixmap = QPixmap(250, 250)
        pixmap.fill(Qt.transparent)
        painter = QPainter(pixmap)
        painter.setPen(QPen(Qt.black, 8))
        painter.translate(125, 125)
        painter.drawPolyline(self._my_polygon)
        # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
        painter.end()
        return pixmap

    def contextMenuEvent(self, event):
        self.scene().clearSelection()
        self.setSelected(True)
        self._my_context_menu.exec(event.screenPos())

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemPositionChange:
            for arrow in self.arrows:
                arrow.updatePosition()

        return value


class DiagramScene(QGraphicsScene):
    InsertItem, InsertLine, InsertText, MoveItem = range(4)

    item_inserted = Signal(DiagramItem)

    text_inserted = Signal(QGraphicsTextItem)

    item_selected = Signal(QGraphicsItem)

    def __init__(self, itemMenu, parent=None):
        super().__init__(parent)

        self._my_item_menu = itemMenu
        self._my_mode = self.MoveItem
        self._my_item_type = DiagramItem.Step
        self.line = None
        self._text_item = None
        self._my_item_color = Qt.white
        self._my_text_color = Qt.black
        self._my_line_color = Qt.black
        self._my_font = QFont()

    def set_line_color(self, color):
        self._my_line_color = color
        if self.is_item_change(Arrow):
            item = self.selectedItems()[0]
            item.set_color(self._my_line_color)
            self.update()

    def set_text_color(self, color):
        self._my_text_color = color
        if self.is_item_change(DiagramTextItem):
            item = self.selectedItems()[0]
            item.setDefaultTextColor(self._my_text_color)

    def set_item_color(self, color):
        self._my_item_color = color
        if self.is_item_change(DiagramItem):
            item = self.selectedItems()[0]
            item.setBrush(self._my_item_color)

    def set_font(self, font):
        self._my_font = font
        if self.is_item_change(DiagramTextItem):
            item = self.selectedItems()[0]
            item.setFont(self._my_font)

    def set_mode(self, mode):
        self._my_mode = mode

    def set_item_type(self, type):
        self._my_item_type = type

    def editor_lost_focus(self, item):
        cursor = item.textCursor()
        cursor.clearSelection()
        item.setTextCursor(cursor)

        if not item.toPlainText():
            self.removeItem(item)
            item.deleteLater()

    def mousePressEvent(self, mouseEvent):
        if (mouseEvent.button() != Qt.LeftButton):
            return

        if self._my_mode == self.InsertItem:
            item = DiagramItem(self._my_item_type, self._my_item_menu)
            item.setBrush(self._my_item_color)
            self.addItem(item)
            item.setPos(mouseEvent.scenePos())
            self.item_inserted.emit(item)
        elif self._my_mode == self.InsertLine:
            self.line = QGraphicsLineItem(QLineF(mouseEvent.scenePos(),
                                        mouseEvent.scenePos()))
            self.line.setPen(QPen(self._my_line_color, 2))
            self.addItem(self.line)
        elif self._my_mode == self.InsertText:
            text_item = DiagramTextItem()
            text_item.setFont(self._my_font)
            text_item.setTextInteractionFlags(Qt.TextEditorInteraction)
            text_item.setZValue(1000.0)
            text_item.lost_focus.connect(self.editor_lost_focus)
            text_item.selected_change.connect(self.item_selected)
            self.addItem(text_item)
            text_item.setDefaultTextColor(self._my_text_color)
            text_item.setPos(mouseEvent.scenePos())
            self.text_inserted.emit(text_item)

        super(DiagramScene, self).mousePressEvent(mouseEvent)

    def mouseMoveEvent(self, mouseEvent):
        if self._my_mode == self.InsertLine and self.line:
            new_line = QLineF(self.line.line().p1(), mouseEvent.scenePos())
            self.line.setLine(new_line)
        elif self._my_mode == self.MoveItem:
            super(DiagramScene, self).mouseMoveEvent(mouseEvent)

    def mouseReleaseEvent(self, mouseEvent):
        if self.line and self._my_mode == self.InsertLine:
            start_items = self.items(self.line.line().p1())
            if len(start_items) and start_items[0] == self.line:
                start_items.pop(0)
            end_items = self.items(self.line.line().p2())
            if len(end_items) and end_items[0] == self.line:
                end_items.pop(0)

            self.removeItem(self.line)
            self.line = None

            if (len(start_items) and len(end_items) and
                    isinstance(start_items[0], DiagramItem) and
                    isinstance(end_items[0], DiagramItem) and
                    start_items[0] != end_items[0]):
                start_item = start_items[0]
                end_item = end_items[0]
                arrow = Arrow(start_item, end_item)
                arrow.set_color(self._my_line_color)
                start_item.add_arrow(arrow)
                end_item.add_arrow(arrow)
                arrow.setZValue(-1000.0)
                self.addItem(arrow)
                arrow.update_position()

        self.line = None
        super(DiagramScene, self).mouseReleaseEvent(mouseEvent)

    def is_item_change(self, type):
        for item in self.selectedItems():
            if isinstance(item, type):
                return True
        return False


class MainWindow(QMainWindow):
    insert_text_button = 10

    def __init__(self):
        super().__init__()

        self.create_actions()
        self.create_menus()
        self.create_tool_box()

        self.scene = DiagramScene(self._item_menu)
        self.scene.setSceneRect(QRectF(0, 0, 5000, 5000))
        self.scene.item_inserted.connect(self.item_inserted)
        self.scene.text_inserted.connect(self.text_inserted)
        self.scene.item_selected.connect(self.item_selected)

        self.create_toolbars()

        layout = QHBoxLayout()
        layout.addWidget(self._tool_box)
        self.view = QGraphicsView(self.scene)
        layout.addWidget(self.view)

        self.widget = QWidget()
        self.widget.setLayout(layout)

        self.setCentralWidget(self.widget)
        self.setWindowTitle("Diagramscene")

    def background_button_group_clicked(self, button):
        buttons = self._background_button_group.buttons()
        for myButton in buttons:
            if myButton != button:
                button.setChecked(False)

        text = button.text()
        if text == "Blue Grid":
            self.scene.setBackgroundBrush(QBrush(QPixmap(':/images/background1.png')))
        elif text == "White Grid":
            self.scene.setBackgroundBrush(QBrush(QPixmap(':/images/background2.png')))
        elif text == "Gray Grid":
            self.scene.setBackgroundBrush(QBrush(QPixmap(':/images/background3.png')))
        else:
            self.scene.setBackgroundBrush(QBrush(QPixmap(':/images/background4.png')))

        self.scene.update()
        self.view.update()

    def button_group_clicked(self, idx):
        buttons = self._button_group.buttons()
        for button in buttons:
            if self._button_group.button(idx) != button:
                button.setChecked(False)

        if idx == self.insert_text_button:
            self.scene.set_mode(DiagramScene.InsertText)
        else:
            self.scene.set_item_type(idx)
            self.scene.set_mode(DiagramScene.InsertItem)

    def delete_item(self):
        for item in self.scene.selectedItems():
            if isinstance(item, DiagramItem):
                item.remove_arrows()
            self.scene.removeItem(item)

    def pointer_group_clicked(self, i):
        self.scene.set_mode(self._pointer_type_group.checkedId())

    def bring_to_front(self):
        if not self.scene.selectedItems():
            return

        selected_item = self.scene.selectedItems()[0]
        overlap_items = selected_item.collidingItems()

        z_value = 0
        for item in overlap_items:
            if (item.zValue() >= z_value and isinstance(item, DiagramItem)):
                z_value = item.zValue() + 0.1
        selected_item.setZValue(z_value)

    def send_to_back(self):
        if not self.scene.selectedItems():
            return

        selected_item = self.scene.selectedItems()[0]
        overlap_items = selected_item.collidingItems()

        z_value = 0
        for item in overlap_items:
            if (item.zValue() <= z_value and isinstance(item, DiagramItem)):
                z_value = item.zValue() - 0.1
        selected_item.setZValue(z_value)

    def item_inserted(self, item):
        self._pointer_type_group.button(DiagramScene.MoveItem).setChecked(True)
        self.scene.set_mode(self._pointer_type_group.checkedId())
        self._button_group.button(item.diagram_type).setChecked(False)

    def text_inserted(self, item):
        self._button_group.button(self.insert_text_button).setChecked(False)
        self.scene.set_mode(self._pointer_type_group.checkedId())

    def current_font_changed(self, font):
        self.handle_font_change()

    def font_size_changed(self, font):
        self.handle_font_change()

    def scene_scale_changed(self, scale):
        new_scale = int(scale[:-1]) / 100.0
        old_matrix = self.view.transform()
        self.view.resetTransform()
        self.view.translate(old_matrix.dx(), old_matrix.dy())
        self.view.scale(new_scale, new_scale)

    def text_color_changed(self):
        self._text_action = self.sender()
        self._font_color_tool_button.setIcon(self.create_color_tool_button_icon(
                    ':/images/textpointer.png',
                    QColor(self._text_action.data())))
        self.text_button_triggered()

    def item_color_changed(self):
        self._fill_action = self.sender()
        self._fill_color_tool_button.setIcon(self.create_color_tool_button_icon(
                    ':/images/floodfill.png',
                    QColor(self._fill_action.data())))
        self.fill_button_triggered()

    def line_color_changed(self):
        self._line_action = self.sender()
        self._line_color_tool_button.setIcon(self.create_color_tool_button_icon(
                    ':/images/linecolor.png',
                    QColor(self._line_action.data())))
        self.line_button_triggered()

    def text_button_triggered(self):
        self.scene.set_text_color(QColor(self._text_action.data()))

    def fill_button_triggered(self):
        self.scene.set_item_color(QColor(self._fill_action.data()))

    def line_button_triggered(self):
        self.scene.set_line_color(QColor(self._line_action.data()))

    def handle_font_change(self):
        font = self._font_combo.currentFont()
        font.setPointSize(int(self._font_size_combo.currentText()))
        if self._bold_action.isChecked():
            font.setWeight(QFont.Bold)
        else:
            font.setWeight(QFont.Normal)
        font.setItalic(self._italic_action.isChecked())
        font.setUnderline(self._underline_action.isChecked())

        self.scene.set_font(font)

    def item_selected(self, item):
        font = item.font()
        color = item.defaultTextColor()
        self._font_combo.setCurrentFont(font)
        self._font_size_combo.setEditText(str(font.pointSize()))
        self._bold_action.setChecked(font.weight() == QFont.Bold)
        self._italic_action.setChecked(font.italic())
        self._underline_action.setChecked(font.underline())

    def about(self):
        QMessageBox.about(self, "About Diagram Scene",
                "The <b>Diagram Scene</b> example shows use of the graphics framework.")

    def create_tool_box(self):
        self._button_group = QButtonGroup()
        self._button_group.setExclusive(False)
        self._button_group.idClicked.connect(self.button_group_clicked)

        layout = QGridLayout()
        layout.addWidget(self.create_cell_widget("Conditional", DiagramItem.Conditional),
                0, 0)
        layout.addWidget(self.create_cell_widget("Process", DiagramItem.Step), 0,
                1)
        layout.addWidget(self.create_cell_widget("Input/Output", DiagramItem.Io),
                1, 0)

        text_button = QToolButton()
        text_button.setCheckable(True)
        self._button_group.addButton(text_button, self.insert_text_button)
        text_button.setIcon(QIcon(QPixmap(':/images/textpointer.png')
                            .scaled(30, 30)))
        text_button.setIconSize(QSize(50, 50))

        text_layout = QGridLayout()
        text_layout.addWidget(text_button, 0, 0, Qt.AlignHCenter)
        text_layout.addWidget(QLabel("Text"), 1, 0, Qt.AlignCenter)
        text_widget = QWidget()
        text_widget.setLayout(text_layout)
        layout.addWidget(text_widget, 1, 1)

        layout.setRowStretch(3, 10)
        layout.setColumnStretch(2, 10)

        item_widget = QWidget()
        item_widget.setLayout(layout)

        self._background_button_group = QButtonGroup()
        self._background_button_group.buttonClicked.connect(self.background_button_group_clicked)

        background_layout = QGridLayout()
        background_layout.addWidget(self.create_background_cell_widget("Blue Grid",
                ':/images/background1.png'), 0, 0)
        background_layout.addWidget(self.create_background_cell_widget("White Grid",
                ':/images/background2.png'), 0, 1)
        background_layout.addWidget(self.create_background_cell_widget("Gray Grid",
                ':/images/background3.png'), 1, 0)
        background_layout.addWidget(self.create_background_cell_widget("No Grid",
                ':/images/background4.png'), 1, 1)

        background_layout.setRowStretch(2, 10)
        background_layout.setColumnStretch(2, 10)

        background_widget = QWidget()
        background_widget.setLayout(background_layout)

        self._tool_box = QToolBox()
        self._tool_box.setSizePolicy(QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Ignored))
        self._tool_box.setMinimumWidth(item_widget.sizeHint().width())
        self._tool_box.addItem(item_widget, "Basic Flowchart Shapes")
        self._tool_box.addItem(background_widget, "Backgrounds")

    def create_actions(self):
        self._to_front_action = QAction(
                QIcon(':/images/bringtofront.png'), "Bring to &Front",
                self, shortcut="Ctrl+F", statusTip="Bring item to front",
                triggered=self.bring_to_front)

        self._send_back_action = QAction(
                QIcon(':/images/sendtoback.png'), "Send to &Back", self,
                shortcut="Ctrl+B", statusTip="Send item to back",
                triggered=self.send_to_back)

        self._delete_action = QAction(QIcon(':/images/delete.png'),
                "&Delete", self, shortcut="Delete",
                statusTip="Delete item from diagram",
                triggered=self.delete_item)

        self._exit_action = QAction("E&xit", self, shortcut="Ctrl+X",
                statusTip="Quit Scenediagram example", triggered=self.close)

        self._bold_action = QAction(QIcon(':/images/bold.png'),
                "Bold", self, checkable=True, shortcut="Ctrl+B",
                triggered=self.handle_font_change)

        self._italic_action = QAction(QIcon(':/images/italic.png'),
                "Italic", self, checkable=True, shortcut="Ctrl+I",
                triggered=self.handle_font_change)

        self._underline_action = QAction(
                QIcon(':/images/underline.png'), "Underline", self,
                checkable=True, shortcut="Ctrl+U",
                triggered=self.handle_font_change)

        self._about_action = QAction("A&bout", self, shortcut="Ctrl+B",
                triggered=self.about)

    def create_menus(self):
        self._file_menu = self.menuBar().addMenu("&File")
        self._file_menu.addAction(self._exit_action)

        self._item_menu = self.menuBar().addMenu("&Item")
        self._item_menu.addAction(self._delete_action)
        self._item_menu.addSeparator()
        self._item_menu.addAction(self._to_front_action)
        self._item_menu.addAction(self._send_back_action)

        self._about_menu = self.menuBar().addMenu("&Help")
        self._about_menu.addAction(self._about_action)

    def create_toolbars(self):
        self._edit_tool_bar = self.addToolBar("Edit")
        self._edit_tool_bar.addAction(self._delete_action)
        self._edit_tool_bar.addAction(self._to_front_action)
        self._edit_tool_bar.addAction(self._send_back_action)

        self._font_combo = QFontComboBox()
        self._font_combo.currentFontChanged.connect(self.current_font_changed)

        self._font_size_combo = QComboBox()
        self._font_size_combo.setEditable(True)
        for i in range(8, 30, 2):
            self._font_size_combo.addItem(str(i))
        validator = QIntValidator(2, 64, self)
        self._font_size_combo.setValidator(validator)
        self._font_size_combo.currentIndexChanged.connect(self.font_size_changed)

        self._font_color_tool_button = QToolButton()
        self._font_color_tool_button.setPopupMode(QToolButton.MenuButtonPopup)
        self._font_color_tool_button.setMenu(
                self.create_color_menu(self.text_color_changed, Qt.black))
        self._text_action = self._font_color_tool_button.menu().defaultAction()
        self._font_color_tool_button.setIcon(
                self.create_color_tool_button_icon(':/images/textpointer.png',
                        Qt.black))
        self._font_color_tool_button.setAutoFillBackground(True)
        self._font_color_tool_button.clicked.connect(self.text_button_triggered)

        self._fill_color_tool_button = QToolButton()
        self._fill_color_tool_button.setPopupMode(QToolButton.MenuButtonPopup)
        self._fill_color_tool_button.setMenu(
                self.create_color_menu(self.item_color_changed, Qt.white))
        self._fill_action = self._fill_color_tool_button.menu().defaultAction()
        self._fill_color_tool_button.setIcon(
                self.create_color_tool_button_icon(':/images/floodfill.png',
                        Qt.white))
        self._fill_color_tool_button.clicked.connect(self.fill_button_triggered)

        self._line_color_tool_button = QToolButton()
        self._line_color_tool_button.setPopupMode(QToolButton.MenuButtonPopup)
        self._line_color_tool_button.setMenu(
                self.create_color_menu(self.line_color_changed, Qt.black))
        self._line_action = self._line_color_tool_button.menu().defaultAction()
        self._line_color_tool_button.setIcon(
                self.create_color_tool_button_icon(':/images/linecolor.png',
                        Qt.black))
        self._line_color_tool_button.clicked.connect(self.line_button_triggered)

        self._text_tool_bar = self.addToolBar("Font")
        self._text_tool_bar.addWidget(self._font_combo)
        self._text_tool_bar.addWidget(self._font_size_combo)
        self._text_tool_bar.addAction(self._bold_action)
        self._text_tool_bar.addAction(self._italic_action)
        self._text_tool_bar.addAction(self._underline_action)

        self._color_tool_bar = self.addToolBar("Color")
        self._color_tool_bar.addWidget(self._font_color_tool_button)
        self._color_tool_bar.addWidget(self._fill_color_tool_button)
        self._color_tool_bar.addWidget(self._line_color_tool_button)

        pointer_button = QToolButton()
        pointer_button.setCheckable(True)
        pointer_button.setChecked(True)
        pointer_button.setIcon(QIcon(':/images/pointer.png'))
        line_pointer_button = QToolButton()
        line_pointer_button.setCheckable(True)
        line_pointer_button.setIcon(QIcon(':/images/linepointer.png'))

        self._pointer_type_group = QButtonGroup()
        self._pointer_type_group.addButton(pointer_button, DiagramScene.MoveItem)
        self._pointer_type_group.addButton(line_pointer_button,
                DiagramScene.InsertLine)
        self._pointer_type_group.idClicked.connect(self.pointer_group_clicked)

        self._scene_scale_combo = QComboBox()
        self._scene_scale_combo.addItems(["50%", "75%", "100%", "125%", "150%"])
        self._scene_scale_combo.setCurrentIndex(2)
        self._scene_scale_combo.currentTextChanged.connect(self.scene_scale_changed)

        self._pointer_toolbar = self.addToolBar("Pointer type")
        self._pointer_toolbar.addWidget(pointer_button)
        self._pointer_toolbar.addWidget(line_pointer_button)
        self._pointer_toolbar.addWidget(self._scene_scale_combo)

    def create_background_cell_widget(self, text, image):
        button = QToolButton()
        button.setText(text)
        button.setIcon(QIcon(image))
        button.setIconSize(QSize(50, 50))
        button.setCheckable(True)
        self._background_button_group.addButton(button)

        layout = QGridLayout()
        layout.addWidget(button, 0, 0, Qt.AlignHCenter)
        layout.addWidget(QLabel(text), 1, 0, Qt.AlignCenter)

        widget = QWidget()
        widget.setLayout(layout)

        return widget

    def create_cell_widget(self, text, diagram_type):
        item = DiagramItem(diagram_type, self._item_menu)
        icon = QIcon(item.image())

        button = QToolButton()
        button.setIcon(icon)
        button.setIconSize(QSize(50, 50))
        button.setCheckable(True)
        self._button_group.addButton(button, diagram_type)

        layout = QGridLayout()
        layout.addWidget(button, 0, 0, Qt.AlignHCenter)
        layout.addWidget(QLabel(text), 1, 0, Qt.AlignCenter)

        widget = QWidget()
        widget.setLayout(layout)

        return widget

    def create_color_menu(self, slot, defaultColor):
        colors = [Qt.black, Qt.white, Qt.red, Qt.blue, Qt.yellow]
        names = ["black", "white", "red", "blue", "yellow"]

        color_menu = QMenu(self)
        for color, name in zip(colors, names):
            action = QAction(self.create_color_icon(color), name, self,
                    triggered=slot)
            action.setData(QColor(color))
            color_menu.addAction(action)
            if color == defaultColor:
                color_menu.setDefaultAction(action)
        return color_menu

    def create_color_tool_button_icon(self, imageFile, color):
        pixmap = QPixmap(50, 80)
        pixmap.fill(Qt.transparent)
        painter = QPainter(pixmap)
        image = QPixmap(imageFile)
        target = QRect(0, 0, 50, 60)
        source = QRect(0, 0, 42, 42)
        painter.fillRect(QRect(0, 60, 50, 80), color)
        painter.drawPixmap(target, image, source)
        painter.end()

        return QIcon(pixmap)

    def create_color_icon(self, color):
        pixmap = QPixmap(20, 20)
        painter = QPainter(pixmap)
        painter.setPen(Qt.NoPen)
        painter.fillRect(QRect(0, 0, 20, 20), color)
        painter.end()

        return QIcon(pixmap)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    main_window = MainWindow()
    main_window.setGeometry(100, 100, 800, 500)
    main_window.show()

    sys.exit(app.exec())
# Resource object code (Python 3)
# Created by: object code
# Created by: The Resource Compiler for Qt version 6.2.2
# WARNING! All changes made in this file will be lost!

from PySide6 import QtCore

qt_resource_data = b"\
\x00\x00\x00\xad\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x0f\x00\x00\x00\x18\x02\x03\x00\x00\x00XkO\xfa\
\x00\x00\x00\x09PLTE\xff\xff\xff\xff\xff\xff\x00\x00\
\x00\x8e\xf4\xc3\xec\x00\x00\x00\x01tRNS\x00@\xe6\
\xd8f\x00\x00\x00RIDAT\x08\x1d\x05\xc1\xb1\x0d\
\xc20\x14\x05\xc0\x8b\x04\x1b\xd0<O\xe3\x8a\x9a\xe6G\
r\x1f\x17a\x1aW\x9e\x80A\xb9\xf3\x82@\xeb\xc8B\
.d g'\xb5H]\xa4\x06\xa9\xb3K\xd5\x92\xfa\
\xfed\xcc\x8f\xdc\x17\xd9\x83\xf6\x1e\xe4\xd8\xdd\xe3\xd8\x1d\
sa.\xb4\x8e'\xf0\x07\xd5\x18\x11\x1b\xedM#\xf4\
\x00\x00\x00\x00IEND\xaeB`\x82\
\x00\x00\x01\x12\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x0b\x00\x00\x00\x0d\x08\x06\x00\x00\x00\x7f\xf5\x94;\
\x00\x00\x00\xd9IDAT(S}\x901\x0eE@\
\x10\x86G$$\x1a\x0d\x0d\xd1\x22Qp\x80m\x5c@\
\xe7<\x0e!\x0aGq\x19\xb5N\xa9\xc1x3\xb2\x8b\
\xf7\xec\xdb\xe4\xcbfv\xfe\xf9gv\xc00\x0c\x04\x80\
\x07\xf4fY\x16&I\x82\x9f\x03\xc4\xbe\xef\x94;\x05\
i\x9a2$\x08\xc3\xf0QX\xd75\x17\x01\x05\x04U\
\xde]\xe8v\x1c\x87s\xb6m\xe3\xc3Y\x0a\xefDQ\
\xc4\xe2 \x08\xf4\xce\xeb\xbab\xdb\xb6j\x94\xbe\xefO\
\xb1|(\x8a\x82\xc9\xf3\x1c}\xdfg\x03!\x04\x0e\xc3\
\xa0L@\xb7\x0d\xd34Y\xdcu\xdd%\xfe\x9ey\xdb\
6\x9c\xa6\x89c\xd9!\x8ec\x1c\xc7\x11\xd5\xcco\x1f\
$d\xbe\xaa\xaa\xff\xdbX\x96E\x8dF]^\xb7A\
\xcc\xf3\x8cM\xd3\xa0\xccgYv9{\x9e\xa7p]\
\xf7\xe7\xd3\xdamH\xa8\xa8,K\xd5\xf1\x00\xd0\xc0\x13\
\xc8\x06\xaf\x16(\x00\x00\x00\x00IEND\xaeB`\
\x82\
\x00\x00\x00r\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x7f\x00\x00\x00\x7f\x01\x03\x00\x00\x00\xfcs\x8fP\
\x00\x00\x00\x06PLTE\xff\xff\xff\x00\x00\x00U\xc2\
\xd3~\x00\x00\x00'IDATH\xc7c`\x80\x82\
\x06\x0640*0*0*0*\x80*\xf0\x1f\x15\
\xfc\x1b\x0d\xa0Q\x81Q\x81Q\x01\x22\x05\x00\xd5;N\
\xf0s\xe3o\xe9\x00\x00\x00\x00IEND\xaeB`\
\x82\
\x00\x00\x00\x8d\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x1b\x00\x00\x00\x1b\x01\x03\x00\x00\x00\xb7\x1af\x16\
\x00\x00\x00\x06PLTE\xff\xff\xff\x00\x00\x00U\xc2\
\xd3~\x00\x00\x00\x01tRNS\x00@\xe6\xd8f\x00\
\x00\x005IDAT\x08\x99c`\xc0\x02\xd8\x1b\x80\
\x04\xff\x01L\x82\xfd\x01H\xba\x00DX\x80\x08\x19\x10\
\xc1\x07\xd6\x02\x22\x98A\xfa\x18A\x0a\x19\xc0\x0a\xeb@\
\x84=\x16B\x0e\xddF\x00\xb5\x00\x09@\xa31\xbf^\
\x00\x00\x00\x00IEND\xaeB`\x82\
\x00\x00\x03?\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x16\x00\x00\x00\x16\x08\x06\x00\x00\x00\xc4\xb4l;\
\x00\x00\x00\x04gAMA\x00\x00\xd6\xd8\xd4OX2\
\x00\x00\x00\x19tEXtSoftware\
\x00Adobe ImageRead\
yq\xc9e<\x00\x00\x02\xd1IDAT8\xcb}\
\x95KhSA\x14\x86\x93\xe6\xd1\x08I(\x04[\x17\
\x055\xeeZ\xbbP\xb2\xb1\xda\x85\x8f]\xb5\xbe\x16v\
)-BIW\xed\xce\x8d\x0a\xa2\xe0\xba\xab\x14\x84\x8a\
+QDE\x17\x0a\x8aU\xf1\x01\x1a\xb0V#\xad\xa2\
\xc5\xb6\x92j\x95\xbe4\xcd\xc3\xe3\x7fn\xced\xe6N\
\xd2\x16>\xe6\xde\xce?\x7ff\xcec\xae\x87\x88<&\
\xf8\xf3\x01~\xa8\x07\x01Pgk\x0cm\x9d\xa1\x0d\xf2\
\xda\xca\x9c!\xf2\x8a\x11Q\x7f\x7f^\x16l\x04a\xe0\
\xafa\xeaw\xb4\x03\x03J\xdb\x08\x22\xe2\xe15\x85\x8e\
\xe9\xbf\xa1!*uwS\xa1,f6\x83(\xcfW\
iS)*\xf5\xf4P)\x18T\xda8hp\xe6\xcd\
\xe3\x97`Z\xec\xed\xa5BK\x0b\xe5\xf0\xfe]\x9bo\
U\xe6\xca\xb44<L\xc5d\x92\x0amm\xb4\x8c\xf7\
q\xad\x8d;Z1\xa6\xd5d2\xbf\x8a\x9d\xe6Z[\
\xe9/\xde\xff\x80\x050\xed^\x10\xe3\xe7\x02L\xa1\xaf\
h'\xc1ep\xd6\xe3)\x8a\xb6I\x19\x87\xf8\x1fK\
`QF\xc5/\xb79\xe5a\x9a\x83\xe9\x0aL\x97\xc4\
t\x04\x1c\xd7\x9av\xd0\xac\x8c\x83\x12|\xfa\x0c\xe6\xc4\
\xf0\xb7\x8c\xccb\x22A+\x83\x83\xb4\xdc\xd7G\x0b0\
\xe5\xb9\x8c\xec\xf4\x986\xed\x02;\x1c/#\xc6aI\
\x14}\x043 +?\xc2\xfc\x88\xc5h\x1e\xf1\xfc\x19\
\x8f;\xef\xef@\x0a\x1c\xd1\xa6\xd8\xb4g\x97x\x84\xed\
\xf2\x89J\xa2\x1cs\x0e\xc1l\x0d\xde\x8b\xe9a\xb7i\
\xbb\x91d\xbf]\x9b\x01\x99\xe0D\xd1\x0c\x8e\xff\x0d;\
\x9d\xc2\xb3\xc9KpA\x9b\x9e\x00\x1d\x95j\x90\xb2\xac\
\xd5M\x01\x95\xfd,b\xfa\x15\xc7\xff\x84g\x13\x0e\xc3\
Mm\xdc\x09\xb6\xcb\x9a@U\xe7\xd9\xc5?\x8f\xecO\
#Q\x13\x88iF\x12\xa5\xf8\x00\xd2\xe0\x896_\xdf\
X\x99\xce\xc1t\x0a%\x95A\xf6\xc7\xc4\xe0\x01x\x05\
\xde\x821\x19\xdf\x80Q\xbb1\xecP\xa8\xde\xcf\xc2\xf4\
\x0bL\xc7a\xca\xbb\xba\x0f.\x81\xd3\xe0*x.\x86\
i\x19\xf9\xc7\x1eUw\xa8\xdf\xd5\xd2\xb3\xe8\xfdI\x98\
\xa6a\xca\x09\xba\x0b\xce\x83\x03F\x83\xdc\x03\xcf\xc0\x0b\
I\x22\x8f\x8f\xc15\xf7\xdd\x12\xae\xb4\xf4\x04n\xa9\x0c\
.\x94\xd7H\x16/\xbc\x0d\xce\x81\xfd\xee\xecw*s\
6{*?rK6\x90\xd4-\xdd\xe8j\xe9\xd1P\
\x88\x1eb\xbc\x0e\xce\x80}\xee:\xed\x90$1tG\
\xc2t\x03\x5c\x04\x87\xb4v\xb7\xdd\xd2M<qE\xe2\
\xb9\xb7\xba\xf8\xd5%\x14Su>R\xbex\xe8\xa0\xd6\
\x1e\x05\x09\xf3\x12\xf2I\xd0\xb7\xb1\xe0\xa4>R\x97\xb4\
\xa9}mV:\xf4\x94\xd6\xb2\xe9\x1e\xf1\x88\xda\xa5\xd6\
\xa0\xcc\xe5H;\xc1\x965.\xfa\xa8\xcc)mB\xd6\
\xea\x8b\xde\xfa4\xf1\x82MN\x9c\xca\xe1\x89\xac\xf3i\
\x8a\x88\xa6Y\xd6\xa8Syku\x9eO>\x8e\x1b\xec\
\x0f\xe4\x1a\xda\xa0h\xebM\xed\x7f=\xa9\x97\x96\x02\xf1\
+\x1c\x00\x00\x00\x00IEND\xaeB`\x82\
\x00\x00\x00t\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x7f\x00\x00\x00\x7f\x01\x03\x00\x00\x00\xfcs\x8fP\
\x00\x00\x00\x06PLTE\xc0\xc0\xc0\xff\xff\xff+i\
\x87\xb4\x00\x00\x00)IDATHKc\xf8\x0f\x05\
\x0d\x0cP0*0*0*0*@\xa4\x00\x0c\xd8\
C\xc4\xff\x8d\x0a\x8c\x0a\x8c\x0a\x8c\x0a`\x17\x00\x00?\
x\xe4\xb7\xe3\x900_\x00\x00\x00\x00IEND\xae\
B`\x82\
\x00\x00\x00`\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x7f\x00\x00\x00\x7f\x01\x03\x00\x00\x00\xfcs\x8fP\
\x00\x00\x00\x03PLTE\xff\xff\xff\xa7\xc4\x1b\xc8\x00\
\x00\x00\x18IDATx^\xed\xc01\x01\x00\x00\x00\
\xc2 \xfb\xa76\xc5>X\x0b\x00\xe0\x08o\x00\x01\x01\
>\xc31\x00\x00\x00\x00IEND\xaeB`\x82\
\x00\x00\x00p\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x7f\x00\x00\x00\x7f\x01\x03\x00\x00\x00\xfcs\x8fP\
\x00\x00\x00\x06PLTE\x00\xff\xff\xff\xff\xff\xb1\xb8\
^\xa0\x00\x00\x00%IDATx^\xed\xcc!\x12\
\x00\x00\x04\x00A\xff\x7f4\x82\x11du/n\xb8\xd8\
j\xca\x0b\x00\x00\xf0\x9d\x01\x00@\x03\x94\x98\xeb\xc0\x19\
8\xa1\x84\x00\x00\x00\x00IEND\xaeB`\x82\
\x00\x00\x01>\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x16\x00\x00\x00\x16\x08\x06\x00\x00\x00\xc4\xb4l;\
\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\xf3IDAT8\xcb\xed\x94An\
\x830\x10E\x9f%\xe0\x0c\xbdC/\xd0\x13\xe5\xfaU\
b\x9b\xd83\x01w\x81\x0d$\x85\xaa1\xca\xaa\x1d\x89\
\x8d\x0dO\xef{\x067m\xdb&\x0e\x94\xaa\x9a\xad\xf5\
\x06@D\xaa\xa0]\xd7\xed\xee5\xbc\xa8\xfe\xc1\x7f\x01\
l\x8c\xd9\xdbJ\x87\x8dS\xda`\x8c\x03\x0c\x01\xf4\x0a\
\xd2Ct\x98\xb7\xf7\x83G1*h\x81z\x10\x07\xd1\
\x1d<\xe3A&\xa0\xf6\x0b48\x88\x97Jp\x1aa\
\x88Kt\xf5\x93e\xb4\xd3#5\xc6i\x80[\x00)\
\xd1=\xa8\x83`W`_\x01\x96\x1c}\xb6|0\x95\
jp\xfep\x06\xba\x15\xd4\xe5\x14v\x01\xfft\xfd\xdd\
U\xb8\xe4\xce\xdb\x05\x5c&A\xfd\xb2\x064{\x17\xf5\
\xe6\x8f\x10\xce\xdf\xa1\xc54\xe6\x89\xa8j^\xf8\x9cF\
j\xb6t\x10\xb3\xa9\xac\x1a\xf84\xf8z\xce\xa6\x16b\
\x0fj\xef\x1bXRT\x81\xa5\x98nLE\xf4p\xeb\
\x9f\x07\x9b\x8f\xd3\xaf\xdf\xfd\x02\xd6\xbd\xde\xdfp\xdb\x04\
\x83\x00\x00\x00\x00IEND\xaeB`\x82\
\x00\x00\x00\xfa\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x0b\x00\x00\x00\x0c\x08\x06\x00\x00\x00\xb4\xa9G\x9e\
\x00\x00\x00\xc1IDAT(S\xcd\x901\x0a\x840\
\x10E\xc7\xceV\xb0\xd3F\x10o`\xe5\x01\xbcB@\
\x0b\x9bt\x22\x11\xbc\x94\x9d'\xd2\x03x\x03\x03\x19\xf7\
\x0f\xb8\xd9,l\xbf\x81Of\xde\xfc|\xc8P\x1c\xc7\
LD\xa2(\x8a8\xcfs~\x1d\xc2\xfd\xc9\xd34e\
\xd2ZsQ\x14\x02\x86a\xe0y\x9e\xc5\x8c\x1b=8\
\xe6\xe382a\xa0\x94\x12\x88\xfa[\xe0\x98;\xe7B\
3\xc0/3\xea\x7fJ\xee\xbaN\xcc\xd7u\x05\x0f\xd0\
\x83\xf7}\xef\x93\xb1&\xc0}\xdf\x03\xf3q\x1c\xc2\x97\
e\xf1\xc9\xeb\xba\x0a\x9c\xa6)0?!\xdb\xb6\xf9d\
\xa8\xaek\x19\x94e\xc9m\xdbrUU\xd27M\xc3\
\xd6Z\x9f\xfc\xc8\x18\xc3Y\x96\x89)I\x12\xc6_\xce\
\xf3|o\xe9\x063 8\xcd\x08\x1exv\x00\x00\x00\
\x00IEND\xaeB`\x82\
\x00\x00\x01%\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x16\x00\x00\x00\x16\x08\x06\x00\x00\x00\xc4\xb4l;\
\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\xdaIDATH\xc7\xed\x94A\x0e\
\x820\x10E\x1fF8\x83w\xf0\xfe\x87\xf0\x1a^@\
\xb1\xa5t\xa6\x1a\x5c\xb4\x04\x8c\xa2\x11\xca\xc2\xc4I\xd8\
\xd0\xe4\xe5\xf5\xf7g\x8a\xb2,;\x16L\x08\xa1x\xf5\
\x7f\x0b\xa0\xaa\xb3\xa0UUM\x9emXi\xfe\xe0\x1f\
\x06o30\xbaU\xc0\xdd\xed\x0a7\x0f\xa1\x05u \
\x96b\xb7\xcf`\x1c\x5c\x826\xa0\x16\xc4f\x8aB\xed\
\x00\xf5\x16\xe4\x92\x09,\x97h)&~\x9a\xcb\xd8\xd7\
\xe0\xcd\x08\xdcd\x02\xbb\xf3`\xaa9\xc1\xed9A\xfb\
\xac\xcd\x00~\xb7\xfe>g\x5c\xc7\x8cC\x93\xe2H\x19\
O-\xeaW\x95\xed\x8e\x87!KI\x96\xbe\x8e\xa6\x92\
\x1a1\xeb\xf1\xfc)V\xaa\xefk\xb0 \xc9TG\x0f\
\xf85\xb8M\xd7V\x03\xe2 \x98\xc7\xaa\xf5\xb7\x98\x05\
\xd6\xde\xd4>\xf7W\x1a\xb8:\x00\x8a\xa5\xcbfj\xee\
\x91a\xa9f\xc0\x0f\xb5]\x00\x00\x00\x00IEND\
\xaeB`\x82\
\x00\x00\x00\x91\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00*\x00\x00\x00+\x01\x03\x00\x00\x004Q\x88\xbd\
\x00\x00\x00\x06PLTE\xff\xff\xff\x00\x00\x00U\xc2\
\xd3~\x00\x00\x00\x01tRNS\x00@\xe6\xd8f\x00\
\x00\x009IDAT\x18Wc`\xc0\x05\x14 T\
\x01\x84\xfa\x01&\x19\xff\x80)f\x08\x8f\xfd\x03\x98\xe2\
\x7f\x00\xa6\xe4\x0f\x80)\xfb\x060U\x0f\xd1\xf6oP\
k\xe3\x87hc\x83P,\x0c\x84\x00\x00\x91\xca\x1c\x09\
\xf6#*\xfe\x00\x00\x00\x00IEND\xaeB`\x82\
\
\x00\x00\x02\xf1\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00*\x00\x00\x00,\x08\x03\x00\x00\x00$D\xdat\
\x00\x00\x012PLTE\xff\xff\xff\xfe\xfe\xfe\x01\x01\
\x01\xbe\xbe\xbe\xfd\xfd\xfd\x00\x00\x00ddd\xd2\xd2\xd2\
|||\xfb\xfb\xfb\xe7\xe7\xe7\x84\x84\x84\xd7\xd7\xd7\xe0\
\xe0\xe0\xe1\xe1\xe1\x0c\x0c\x0c(((\xf5\xf5\xf5\xb3\xb3\
\xb3\x02\x02\x02\x95\x95\x95...\x11\x11\x11kkk\
\x03\x03\x03rrrIII\xfc\xfc\xfc\x13\x13\x13\x04\
\x04\x04\x9f\x9f\x9f\xc4\xc4\xc4\xa9\xa9\xa9\x05\x05\x05WW\
W\x17\x17\x17\xf6\xf6\xf6\x16\x16\x16\xa6\xa6\xa6\xa0\xa0\xa0\
```$$$>>>###\xb7\xb7\xb7M\
MM\xf8\xf8\xf8\xc0\xc0\xc0000\x09\x09\x09\xec\xec\
\xec   \x8a\x8a\x8a\xda\xda\xda\xf1\xf1\xf1\x0d\x0d\x0d\
\x99\x99\x99\x19\x19\x19\xf9\xf9\xf9\xcd\xcd\xcd\xf4\xf4\xf49\
99---;;;\x12\x12\x12CCC\xc2\xc2\
\xc2\xa4\xa4\xa4\xdc\xdc\xdcUUUhhhZZZ\
PPP\xf0\xf0\xf0\x06\x06\x06\x1f\x1f\x1fttt\xb1\
\xb1\xb1]]]!!!666\x08\x08\x08\xea\xea\
\xea\xdb\xdb\xdb\x81\x81\x81\x9c\x9c\x9c\x8b\x8b\x8buuu\
\xf2\xf2\xf2%%%\xce\xce\xceHHHccc\xba\
\xba\xbaSSS888\xf7\xf7\xf7\xe4\xe4\xe4\xa2\xa2\
\xa2JJJ\xf3\xf3\xf3___\xf1i\x00\xec\x00\x00\
\x00\x01tRNS\x00@\xe6\xd8f\x00\x00\x01mI\
DATx^\xd5\x92\xc5v\xc30\x10E=\x92\x1d\
f\xe6\x94\x99\x99\x99\x99\x99\xe1\xff\x7f\xa1\x9e\x89\x93S\
\xa9\xb2Nvm\xdf\xf2\xea\xfa\xbdY\xd8\xf8+\xf10\
\xeb[X\xcc\x047\x13<\x96\x10\xc6\xb5\xadB\xda\x9a\
om\x0d@\xb3\xad,\xe8\xda\x1a\xe2\xb5\xf4\xd4\xddq\
\xbf\xa1\x0d\x14{\x1b\xed\x09\xd0\xbb\x03\x0d\x93\x0d\xeaM\
\xd8A+3\x82n.\xac5\xc39\xbb\x95\xe5\xbb\xa9\
\xdb\xa7\xbd\xc0G\xcedG'~1;\xa7q\x87\xda\
\xd1,\x00\xf8\xe8\xda\x16\xcd~\x17\x19\x09\xc3\x88\x94\xd1\
]\xd5\xb4\xf6\xe1n\xbf\xdf66\xe9\x92\x90\xab\xeb\xa5\
\xf7\x09\xdb\x84a\xea\xcf\xbb\xeeg\xd1\x1c\x1dC`\xa6\
\xd1]\x89\xbb\x98S\xd3\xb8\xef\xa9\x81\x19Z\xa8\x80\xda\
M\xd1\xeb<\xbd\xc2B\x06\xbf[T\x9b\xe6\x12\x9a\xcb\
N\x0f\x1c\xd0\xb5w\xca\xfd5z[\xaf\x83\x8d$\xba\
[\xca\x0b\xb6q_\x0a\x8b\xee*\xdc\xc0\x9e\xa5\x08K\
)\xf6\x83\x962i\xf3\x87\xe9\xdfgj\xb7\x0a\xb2{\
\xe8b\xb2#\xd9\x84\x02\xf2c.\xe4\x04\xd9\xe9\x99d\
\x9eS\xc3\x85H/i\xe9\x0aDzmS\x96\x8c\x08\
\x14n\xa2Ho\x8b\x02\x8d\x97\xb0\xf5\x1e\xa4\xad\x07\xda\
z\x14XE\xfd\xd7W\xe9\x82'\xa1\xe1\x19\x97J/\
r\xab\x19C^~\xads\xce\xf9\x1b}\xfd\xce1\x1f\
\xe0`\xcc'\xademL\xcc\x12\xc2\xbcN#\x139\
A\x89y\xc1P5\xfc~\xeb\xff\xca\x17Uq \xbb\
\xd7\xbb.\xca\x00\x00\x00\x00IEND\xaeB`\x82\
\
\x00\x00\x01\x1a\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00*\x00\x00\x00+\x02\x03\x00\x00\x00s\xf1\xf2m\
\x00\x00\x00\x0cPLTE\xff\xff\xff\x80\x80\x80\x00\x00\
\x00\xff\xff\xffEJK8\x00\x00\x00\x01tRNS\
\x00@\xe6\xd8f\x00\x00\x00\xbcIDATx^M\
\xcb\xbd\x89\x041\x0c\x86a\xa1\xd0U8\x1c\xdc\x8f&\
\xd8\x12\xa6\x0a\xb3\xe1\xe6N.2\x07\x02\xdb\x07[\xc0\
\x96\xb4U\x9cG?3V\xf4!\xde\x07B\xcd\xe0\x17\
F\xbd\xf6\xb6\xec\x1a\xef\xa6A\x024\xb2A\x80`$\
\xcf\x9d\x9a\xee8\x8b~x\x83O~d\xb30hW\
\x102t\x22\x05\x98\x91\x89\x0c\xe4P\x88\x0c\xd4D\xe4\
 \xce\xdc\xc1\x98\x89\x833q \x89\x02\xe4\x9d\x1d`\
\xa1.@\xff\xe9\x02\xfd\xf1*\x0e\xd2\xfe{\x81P\xda\
\x02\x8e\xef\x02>\x0bx\xb3l\x01\x7f]\x1a\x03f\x1d\
4\x00\x03B\x15\xb0\xe4\x0a$7P$W\xc0\x92+\
\xe8\x92\x1b\x90\xdc\x80\xe4\x0a$7\xf0so\x1cp_\
[v<\xc7?\xd6Qh R\x85\xdb_\x00\x00\x00\
\x00IEND\xaeB`\x82\
\x00\x00\x00\xf7\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x0b\x00\x00\x00\x0c\x08\x06\x00\x00\x00\xb4\xa9G\x9e\
\x00\x00\x00\xbeIDAT(S\x85\x911\x0e@@\
\x10EWM$J7\xa1\xa4\x918\x85^t\xaa=\
\x8aNT{\x80\xadun\xa0\xd1l\xe7\x12\xc4\x97\x19\
\xb1!YQ\xfcb\xfe\xbc\xfc\x99\xcc\x08\x00\x82t\x1c\
\x07\xa6i\x82\x10\xc2)\xcf\xf3.\xf0\xd68\x8e\xa8\xaa\
\x8aU\x14\x05\x03I\x92X\xef\x05?\xd5u\x1d\xc3Z\
k\xd0T\xf2\x9c 5\xeb\xbafx]W\xdc\xfeg\
r\x9a\xa6\x88\xe3\x18O\xcf\x09n\xdb\x06\xdf\xf7Q\x96\
\xa5]\xc1\x09Ss\x9eg^AJ\xf9\x9f<\x0c\x03\
\xc3J\xa9\xff\xe4\xb6m\x19^\x96\xe5?9\xcfs\x84\
a\x88}\xdf\xdf\xc9T\x18c\xec\xe1IA\x10 \x8a\
\x22[7M\x03\x9b\xdc\xf7\xfd\xf5\xce\x8fWgY\xc6\
\x13N\xfaWVX\xe8@\xda\xc6\x00\x00\x00\x00IE\
ND\xaeB`\x82\
"

qt_resource_name = b"\
\x00\x06\
\x07\x03}\xc3\
\x00i\
\x00m\x00a\x00g\x00e\x00s\
\x00\x0b\
\x0a+\x97\xe7\
\x00p\
\x00o\x00i\x00n\x00t\x00e\x00r\x00.\x00p\x00n\x00g\
\x00\x08\
\x06'Zg\
\x00b\
\x00o\x00l\x00d\x00.\x00p\x00n\x00g\
\x00\x0f\
\x00I\xdb\xa7\
\x00b\
\x00a\x00c\x00k\x00g\x00r\x00o\x00u\x00n\x00d\x002\x00.\x00p\x00n\x00g\
\x00\x0f\
\x03J#\xe7\
\x00l\
\x00i\x00n\x00e\x00p\x00o\x00i\x00n\x00t\x00e\x00r\x00.\x00p\x00n\x00g\
\x00\x0a\
\x0c\xad\x0f\x07\
\x00d\
\x00e\x00l\x00e\x00t\x00e\x00.\x00p\x00n\x00g\
\x00\x0f\
\x00J\xdb\xa7\
\x00b\
\x00a\x00c\x00k\x00g\x00r\x00o\x00u\x00n\x00d\x003\x00.\x00p\x00n\x00g\
\x00\x0f\
\x00K\xdb\xa7\
\x00b\
\x00a\x00c\x00k\x00g\x00r\x00o\x00u\x00n\x00d\x004\x00.\x00p\x00n\x00g\
\x00\x0f\
\x00P\xdb\xa7\
\x00b\
\x00a\x00c\x00k\x00g\x00r\x00o\x00u\x00n\x00d\x001\x00.\x00p\x00n\x00g\
\x00\x0e\
\x0f\x0d\x22'\
\x00s\
\x00e\x00n\x00d\x00t\x00o\x00b\x00a\x00c\x00k\x00.\x00p\x00n\x00g\
\x00\x0d\
\x08\xd5\xc4\xe7\
\x00u\
\x00n\x00d\x00e\x00r\x00l\x00i\x00n\x00e\x00.\x00p\x00n\x00g\
\x00\x10\
\x0f\x9b\x88g\
\x00b\
\x00r\x00i\x00n\x00g\x00t\x00o\x00f\x00r\x00o\x00n\x00t\x00.\x00p\x00n\x00g\
\x00\x0d\
\x05l\x22\xc7\
\x00l\
\x00i\x00n\x00e\x00c\x00o\x00l\x00o\x00r\x00.\x00p\x00n\x00g\
\x00\x0f\
\x05\xaa\x0c\xc7\
\x00t\
\x00e\x00x\x00t\x00p\x00o\x00i\x00n\x00t\x00e\x00r\x00.\x00p\x00n\x00g\
\x00\x0d\
\x06C\xe3g\
\x00f\
\x00l\x00o\x00o\x00d\x00f\x00i\x00l\x00l\x00.\x00p\x00n\x00g\
\x00\x0a\
\x02\xfcBG\
\x00i\
\x00t\x00a\x00l\x00i\x00c\x00.\x00p\x00n\x00g\
"

qt_resource_struct = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x0f\x00\x00\x00\x02\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00D\x00\x00\x00\x00\x00\x01\x00\x00\x01\xc7\
\x00\x00\x01z\xe7\xee'\x09\
\x00\x00\x00\xa6\x00\x00\x00\x00\x00\x01\x00\x00\x06\x11\
\x00\x00\x01z\xe7\xee'\x09\
\x00\x00\x00\xca\x00\x00\x00\x00\x00\x01\x00\x00\x06\x89\
\x00\x00\x01z\xe7\xee'\x09\
\x00\x00\x00\xee\x00\x00\x00\x00\x00\x01\x00\x00\x06\xed\
\x00\x00\x01z\xe7\xee'\x09\
\x00\x00\x01\xde\x00\x00\x00\x00\x00\x01\x00\x00\x0fr\
\x00\x00\x01z\xe7\xee'\x09\
\x00\x00\x00h\x00\x00\x00\x00\x00\x01\x00\x00\x02=\
\x00\x00\x01z\xe7\xee'\x09\
\x00\x00\x01z\x00\x00\x00\x00\x00\x01\x00\x00\x0a\xca\
\x00\x00\x01z\xe7\xee'\x09\
\x00\x00\x01\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x0b_\
\x00\x00\x01z\xe7\xee'\x09\
\x00\x00\x00.\x00\x00\x00\x00\x00\x01\x00\x00\x00\xb1\
\x00\x00\x01z\xe7\xee'\x09\
\x00\x00\x01\xbe\x00\x00\x00\x00\x00\x01\x00\x00\x0eT\
\x00\x00\x01z\xe7\xee'\x09\
\x00\x00\x014\x00\x00\x00\x00\x00\x01\x00\x00\x08\xa3\
\x00\x00\x01z\xe7\xee'\x09\
\x00\x00\x00\x12\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01z\xe7\xee'\x09\
\x00\x00\x00\x8c\x00\x00\x00\x00\x00\x01\x00\x00\x02\xce\
\x00\x00\x01z\xe7\xee'\x09\
\x00\x00\x01\x12\x00\x00\x00\x00\x00\x01\x00\x00\x07a\
\x00\x00\x01z\xe7\xee'\x09\
\x00\x00\x01T\x00\x00\x00\x00\x00\x01\x00\x00\x09\xa1\
\x00\x00\x01z\xe7\xee'\x09\
"

def qInitResources():
    QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)

def qCleanupResources():
    QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)

qInitResources()