Esempio n. 1
0
 def set_shadow(self, on):
     if on:
         self._shadow = QGraphicsDropShadowEffect(self)
         self._shadow.setOffset(0.0, 0.0)
         self._shadow.color()
         self.setGraphicsEffect(self._shadow)
         self.setGeometry(5, 5, self.width() - 5, self.height() - 5)
Esempio n. 2
0
    def __init__(self, parent, piece_type, row, col, move=False):
        super(Piece, self).__init__(parent)
        self.main_window = parent.parent().parent().parent(
        )  # CenterWidget >> AspectRatioWidget >> MainWindow
        # self.move(0, 0)
        # self.resize(50, 50)
        self.setStyleSheet("background: " + "red; border-radius: 50px")
        self.border_radius = 10
        self.offset = QPoint()
        self.crs = QCursor()
        self.table_width = 50
        self.piece_type = piece_type
        self.col = col
        self.row = row
        self.movable = move
        self.possible_jumps = []
        self.animator = QPropertyAnimation(self, b"geometry")
        self.styles = {}

        self.shadow = QGraphicsDropShadowEffect()
        self.shadow.setBlurRadius(0)
        self.shadow.setXOffset(0)
        self.shadow.setYOffset(0)
        self.setGraphicsEffect(self.shadow)
        self.confirm_jump_stop = False
Esempio n. 3
0
        def uiDefinitions():

            # REMOVE TITLE BAR
            self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
            self.setAttribute(QtCore.Qt.WA_TranslucentBackground)

            # SET DROPSHADOW WINDOW
            self.shadow = QGraphicsDropShadowEffect(self)
            self.shadow.setBlurRadius(20)
            self.shadow.setXOffset(0)
            self.shadow.setYOffset(0)
            self.shadow.setColor(QColor(0, 0, 0, 100))

            # APPLY DROPSHADOW TO FRAME
            self.ui.drop_shadow_frame.setGraphicsEffect(self.shadow)

            # MAXIMIZE / RESTORE
            self.ui.maximize_btn.clicked.connect(lambda: maximize_restore())

            # MINIMIZE
            self.ui.minimize_btn.clicked.connect(lambda: self.showMinimized())

            # CLOSE
            self.ui.close_btn.clicked.connect(lambda: self.close())

            ## ==> CREATE SIZE GRIP TO RESIZE WINDOW
            self.sizegrip = QSizeGrip(self.ui.frame_grip)
            self.sizegrip.setStyleSheet(
                "QSizeGrip { width: 10px; height: 10px; margin: 5px } QSizeGrip:hover { background-color: rgb(50, 42, 94) }"
            )
            self.sizegrip.setToolTip("Resize Window")
Esempio n. 4
0
 def subTimeOut(self):
     fontColor = self.previewSubtitle.fontColor
     fontSize = (self.previewSubtitle.fontSize + 5) / 2.5
     fontBold = self.previewSubtitle.bold
     fontItalic = self.previewSubtitle.italic
     fontShadowOffset = self.previewSubtitle.shadowOffset
     for _, srtTextItem in self.srtTextItemDict.items():
         srtTextItem.setDefaultTextColor(fontColor)
         font = QFont()
         font.setFamily("微软雅黑")
         font.setPointSize(fontSize)
         font.setBold(fontBold)
         font.setItalic(fontItalic)
         srtTextItem.setFont(font)
         srtTextShadow = QGraphicsDropShadowEffect()
         srtTextShadow.setOffset(fontShadowOffset)
         srtTextItem.setGraphicsEffect(srtTextShadow)
     try:
         selected = self.subtitle.selectionModel().selection().indexes()
         for x, i in enumerate(selected):
             if self.subtitle.item(i.row(), x):
                 txt = self.subtitle.item(i.row(), x).text()
                 if txt:
                     self.srtTextItemDict[x].setPlainText('#%s:' % (x + 1) + txt)
                     txtSize = self.srtTextItemDict[x].boundingRect().size()
                     posY = self.playerWidget.size().height() - txtSize.height() * (x + 1)
                     posX = (self.playerWidget.size().width() - txtSize.width()) / 2
                     self.srtTextItemDict[x].setPos(posX, posY)
                 else:
                     self.srtTextItemDict[x].setPlainText('')
             else:
                 self.srtTextItemDict[x].setPlainText('')
     except:
         pass
Esempio n. 5
0
    def __init__(self):
        super().__init__()
        # Objects
        self.overallLayout = QVBoxLayout(self)
        self.contentLayout = QHBoxLayout()
        self.dropShadow = QGraphicsDropShadowEffect(self)
        self.boxManager = BoxManager.BoxManager()
        self.topBar = TopBar.TopBar()
        self.selectorArea = QFrame()
        self.selectorLayout = QVBoxLayout(self.selectorArea)
        self.folderArea = QFrame()
        self.folderLayout = QHBoxLayout(self.folderArea)
        self.folderList = FolderList.FolderList()
        self.folderBar = ScrollBar.ScrollBar(self.folderList)
        self.canvas = Canvas.Canvas(self.boxManager)
        self.imageArea = QFrame()
        self.imageList = ImageList.ImageList()
        self.imageLayout = QHBoxLayout(self.imageArea)
        self.imageBar = ScrollBar.ScrollBar(self.imageList)

        # Styling
        self.setStyleSheet('Central { background: transparent; }')
        self.overallLayout.setMargin(20)
        self.overallLayout.setSpacing(0)
        self.dropShadow.setOffset(QPointF(0,4))
        self.dropShadow.setColor(QColor(0,0,0,100))
        self.dropShadow.setBlurRadius(10)
        self.setGraphicsEffect(self.dropShadow)
        self.contentLayout.setAlignment(Qt.AlignCenter)
        self.contentLayout.setMargin(0)        
        self.contentLayout.setSpacing(0)
        self.selectorLayout.setMargin(0)
        self.selectorLayout.setSpacing(0)
        self.folderLayout.setMargin(0)
        self.folderLayout.setSpacing(0)
        self.imageLayout.setMargin(0)
        self.imageLayout.setSpacing(0)
        self.folderList.setVerticalScrollBar(self.folderBar)
        self.imageList.setVerticalScrollBar(self.imageBar)
        self.selectorArea.setMaximumWidth(400)
        self.selectorArea.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        # Layout
        self.folderLayout.addWidget(self.folderList)
        self.folderLayout.addSpacerItem(QSpacerItem(-7, 0))
        self.folderLayout.addWidget(self.folderBar)
        self.imageLayout.addWidget(self.imageList)
        self.imageLayout.addSpacerItem(QSpacerItem(-7, 0))
        self.imageLayout.addWidget(self.imageBar)
        self.selectorLayout.addWidget(self.folderArea, 15)
        self.selectorLayout.addWidget(self.imageArea, 85)
        self.contentLayout.addWidget(self.selectorArea, 30)
        self.contentLayout.addWidget(self.canvas, 70)
        self.overallLayout.addLayout(self.contentLayout)
        self.overallLayout.insertWidget(0, self.topBar)

        # Connections
        self.folderList.selectedFolderChanged.connect(self.handleSelectedFolderChanged)
        self.imageList.selectedImageChanged.connect(self.handleSelectedImageChanged)
Esempio n. 6
0
    def button_shadow(self):
        effect = QGraphicsDropShadowEffect(self.window)

        effect.setColor(QColor(0, 0, 0, 100))
        effect.setXOffset(1)
        effect.setYOffset(1)
        effect.setBlurRadius(5)

        return effect
Esempio n. 7
0
    def card_shadow(self):
        effect = QGraphicsDropShadowEffect(self.main_widget)

        effect.setColor(QColor(0, 0, 0, 100))
        effect.setXOffset(2)
        effect.setYOffset(2)
        effect.setBlurRadius(5)

        return effect
Esempio n. 8
0
 def add_window_drop_shadow() -> None:
     """Adds a drop-shadow behind the window"""
     if self.__use_shadow:
         self.layout().setMargin(self.__style.window.SHADOW_RADIUS_PX)
         drop_shadow_effect = QGraphicsDropShadowEffect(self)
         drop_shadow_effect.setEnabled(True)
         drop_shadow_effect.setBlurRadius(
             self.__style.window.SHADOW_RADIUS_PX)
         color = QColor(self.__style.window.SHADOW_COLOR_RGB)
         color.setAlpha(self.__style.window.SHADOW_OPACITY_HEX)
         drop_shadow_effect.setColor(color)
         drop_shadow_effect.setOffset(0)
         self.setGraphicsEffect(drop_shadow_effect)
Esempio n. 9
0
def css_button(qtwindow, button, color=None, shadow=True):
    ''' apply style to a button widget '''

    # default bg color is gray 80
    if color == 'red':
        bg_color = 'rgb(160, 20, 20)'  # red/white
        tx_color = 'rgb(255, 255, 255)'
    elif color == 'disabled':
        bg_color = 'rgb(80, 80, 80)'  # gray/gray
        tx_color = 'rgb(180, 180, 180)'
    elif color == 'blue':
        bg_color = 'rgb(46, 134, 193)'  # blue arcane/white
        tx_color = 'rgb(230, 230, 230)'
    else:
        bg_color = 'rgb(80, 80, 80)'  # gray
        tx_color = 'rgb(230, 230, 230)'

    css = "border-radius:3px;color:{};background:{};font-size:12px;font-family:Segoe UI;".format(
        tx_color, bg_color)
    button.setStyleSheet(css)

    if shadow:
        shadow = QGraphicsDropShadowEffect(qtwindow)
        shadow.setBlurRadius(6)
        shadow.setOffset(4)
        shadow.setColor(QColor(20, 20, 20, 200))
        button.setGraphicsEffect(shadow)
Esempio n. 10
0
    def overlay_text(
        self,
        message: str,
        color: int,
        size: int,
        x: int,
        y: int,
        timeout: int,
        font_name: str,
        centered: bool,
        shadow: bool,
    ):
        gfx = QGraphicsTextItem(message)
        gfx.setDefaultTextColor(decode_color(color))

        font = QFont(font_name, min(50, size))
        font.setStyleHint(QFont.SansSerif)
        gfx.setFont(font)

        if shadow:
            effect = QGraphicsDropShadowEffect(gfx)
            effect.setBlurRadius(0)
            effect.setColor(Qt.GlobalColor.black)
            effect.setOffset(1, 1)
            gfx.setGraphicsEffect(effect)

        if centered:
            # The provided x, y is at the center of the text
            bound = gfx.boundingRect()
            gfx.setPos(x - (bound.width() / 2), y - (bound.height() / 2))
        else:
            gfx.setPos(x, y)

        self._finalize_gfx(gfx, timeout)
Esempio n. 11
0
    def __init__(self, base_path, file, file_config, parent=None):
        super().__init__(parent)

        board = BanBoard(file, file_config)
        board_area = QScrollArea()
        board_area.setWidget(board)
        board_area.setWidgetResizable(True)
        self.setCentralWidget(board_area)

        self.stbar = QStatusBar()

        # add a save button at the right bottom corner
        save_btn = BanButton(
            "save",
            objectName="appBtn_save",
            toolTip="save xban file",
            shortcut="Ctrl+S",
        )

        shadow = QGraphicsDropShadowEffect(self,
                                           blurRadius=10,
                                           offset=5,
                                           color=QColor("lightgrey"))
        save_btn.setGraphicsEffect(shadow)
        save_btn.pressed.connect(board.save_board)

        self.stbar.addPermanentWidget(save_btn)
        self.setStatusBar(self.stbar)
        log_handler = QLogHandler(self)
        root_logger = logging.getLogger()
        root_logger.addHandler(log_handler)
        log_handler.signal.log_msg.connect(
            partial(self.stbar.showMessage, timeout=1500))
        self.stbar.showMessage(f"Initiate {file}", 1500)
        self.show()
Esempio n. 12
0
 def __init__(self, parent=None):
     super(airWidget, self).__init__(parent)
     self.desktop = ''
     box = QGridLayout()
     box.setColumnStretch(0, -1)
     box.setColumnStretch(1, 1)
     self.btn_icon = QPushButton()
     effect = QGraphicsDropShadowEffect(blurRadius=5, xOffset=3, yOffset=3)
     self.btn_icon.setGraphicsEffect(effect)
     self.btn_icon.setIconSize(QSize(64, 64))
     self.btn_icon.setMinimumHeight(72)
     self.btn_icon.clicked.connect(self._executeAir)
     box.addWidget(self.btn_icon, 0, 0, 2, 1, Qt.AlignLeft)
     self.lbl_name = QLabel("")
     self.lbl_name.setObjectName("appName")
     box.addWidget(self.lbl_name, 0, 1, 1, 1, Qt.AlignLeft)
     self.lbl_desc = QLabel("")
     box.addWidget(self.lbl_desc, 1, 1, 1, 2, Qt.AlignLeft)
     btn_remove = QPushButton(_("Remove"))
     btn_remove.setObjectName("btnRemove")
     btn_remove.clicked.connect(self._removeAir)
     box.addWidget(btn_remove, 0, 2, 1, 1, Qt.AlignLeft)
     self.setObjectName("cell")
     self.setLayout(box)
     self.setStyleSheet(self._setCss())
Esempio n. 13
0
    def __init__(self, ):
        ui_file = QFile("resources/ui/splashscreen.ui")
        ui_file.open(QFile.ReadOnly)
        loader = QUiLoader()
        self.window = loader.load(ui_file)
        ui_file.close()

        if not self.window:
            print(loader.errorString())
            sys.exit(-1)

        self.window.setWindowFlag(QtCore.Qt.FramelessWindowHint)
        self.window.setAttribute(QtCore.Qt.WA_TranslucentBackground)

        ## DROP SHADOW EFFECT
        self.window.shadow = QGraphicsDropShadowEffect(self.window)
        self.window.shadow.setBlurRadius(30)
        self.window.shadow.setXOffset(0)
        self.window.shadow.setYOffset(0)
        self.window.shadow.setColor(QColor(0, 0, 0, 90))
        self.window.dropShadowFrame.setGraphicsEffect(self.window.shadow)
        self.counter = 0

        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.progress)
Esempio n. 14
0
        def uiDefinition():
            # REMOVE TITLE BAR
            self.shadow = QGraphicsDropShadowEffect(self)
            self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
            self.setAttribute(QtCore.Qt.WA_TranslucentBackground)

            # SET DROPSHADOW WINDOW
            self.shadow.setBlurRadius(20)
            self.shadow.setXOffset(0)
            self.shadow.setYOffset(0)
            self.shadow.setColor(QColor(0, 0, 0, 100))

            # APPLY DROPSHADOW TO FRAME
            self.ui.login_frame.setGraphicsEffect(self.shadow)

            # CLOSE
            self.ui.closePushButton.clicked.connect(lambda: self.close())
Esempio n. 15
0
    def update_design(self):
        """Loads the shadow effect option and causes redraw with active theme."""

        if Design.node_instance_shadows_shown:
            self.shadow_effect = QGraphicsDropShadowEffect()
            self.shadow_effect.setXOffset(12)
            self.shadow_effect.setYOffset(12)
            self.shadow_effect.setBlurRadius(20)
            self.shadow_effect.setColor(QColor('#2b2b2b'))
            self.setGraphicsEffect(self.shadow_effect)
        else:
            self.setGraphicsEffect(None)

        self.title_label.update_design()
        # print(self.title_label.color)
        self.animator.reload_values()

        QGraphicsItem.update(self)
Esempio n. 16
0
    def __init__(self, text: str, object_name: str = "blue"):
        super().__init__(text)

        self.setCursor(Qt.PointingHandCursor)

        if object_name:
            self.setObjectName(object_name)

        effect = QGraphicsDropShadowEffect(self)
        effect.setColor(QColor(0, 0, 0, 0.25 * 255))
        effect.setOffset(2, 4)
        effect.setBlurRadius(4)
        self.setGraphicsEffect(effect)
Esempio n. 17
0
    def draw_board(self, file_config):
        """Initiate UI

        The UI consists of 2 parts, top is the board title and info
        and button is the subbords with tiles in each ones
        the subboard is drawn based on file_configuration
        """
        config, content = file_config

        mainlayout = QVBoxLayout()
        mainlayout.setContentsMargins(20, 20, 20, 20)

        title_edit = QLineEdit(config["xban_config"]["title"], self)
        title_edit.setPlaceholderText("Enter title here ...")
        title_edit.setStyleSheet(
            'font-family: "Courier New"; font-size: 24px; font-weight: bold;')

        info_edit = NoteTile(config["xban_config"]["description"], self)
        info_edit.setPlaceholderText("Enter description here ...")
        info_edit.setStyleSheet(
            "font-size: 14px; background-color:transparent;")

        mainlayout.addWidget(title_edit)
        mainlayout.addWidget(info_edit)

        sublayout = QHBoxLayout()
        color = config["xban_config"]["board_color"]
        sublayout.setMargin(10)
        sublayout.setSpacing(20)

        for i, tile_contents in enumerate(content.items()):
            subboard = SubBoard(tile_contents, color[i], self)
            sublayout.addWidget(subboard)
            subboard.delboardSig.connect(
                partial(self.delete_board, board=subboard))

        add_btn = QPushButton("+",
                              clicked=self.insert_board,
                              toolTip="add board")
        shadow = QGraphicsDropShadowEffect(self,
                                           blurRadius=10,
                                           offset=5,
                                           color=QColor("lightgrey"))
        add_btn.setGraphicsEffect(shadow)
        add_btn.setFixedWidth(30)
        add_btn.setStyleSheet("border-style: none ")
        sublayout.addWidget(add_btn)

        save_shortcut = QShortcut(QKeySequence("Ctrl+S"), self)
        save_shortcut.activated.connect(self.save_board)

        mainlayout.addLayout(sublayout)
        self.setLayout(mainlayout)
Esempio n. 18
0
    def initUI(self, windowInst):
        # self.app = QtWidgets.QApplication(sys.argv)
        self.ui = Ui_PreferencesDialog()
        self.ui.windowInst = windowInst
        self.ui.windowInst.hide()
        self.ui.setupUi(self.ui.windowInst)

        windowInst.setAttribute(Qt.WA_TranslucentBackground)
        self.backgroundEffect = QGraphicsDropShadowEffect(windowInst)
        self.backgroundEffect.setBlurRadius(30)
        self.backgroundEffect.setOffset(0, 0)
        self.backgroundEffect.setEnabled(True)

        self.ui.centralwidget.setGraphicsEffect(self.backgroundEffect)

        self.ui.comboBoxAutosaveMode.addItem("Don't Autosave")
        self.ui.comboBoxAutosaveMode.addItem("5 min Autosave")
        self.ui.comboBoxAutosaveMode.addItem("10 min Autosave")
        self.ui.comboBoxAutosaveMode.addItem("15 min Autosave")
        self.ui.comboBoxAutosaveMode.addItem("20 min Autosave")

        self.ui.comboBoxThemeSelect.addItem("Dark Theme")
        self.ui.comboBoxThemeSelect.addItem("Light Theme")
Esempio n. 19
0
    def draw_board(self, file_config):
        """Initiate UI

        The UI consists of 2 parts, top is the board title and info
        and button is the subbords with tiles in each ones
        the subboard is drawn based on file_configuration
        """
        config, content = file_config

        mainlayout = QVBoxLayout()
        mainlayout.setContentsMargins(20, 20, 20, 20)

        title_edit = QLineEdit(
            config["xban_config"]["title"],
            objectName="windowEdit_title",
            parent=self,
        )
        title_edit.setPlaceholderText("Enter title here ...")

        info_edit = NoteTile(config["xban_config"]["description"],
                             "windowEdit_text", self)
        info_edit.setPlaceholderText("Enter description here ...")

        mainlayout.addWidget(title_edit)
        mainlayout.addWidget(info_edit)

        self.sublayout = QHBoxLayout()
        color = config["xban_config"]["board_color"]
        self.sublayout.setMargin(10)
        self.sublayout.setSpacing(20)

        add_btn = BanButton(
            "+",
            clicked=self.insert_board,
            toolTip="add board",
            objectName="windowBtn_add",
        )
        shadow = QGraphicsDropShadowEffect(self,
                                           blurRadius=10,
                                           offset=5,
                                           color=QColor("lightgrey"))
        add_btn.setGraphicsEffect(shadow)
        self.sublayout.addWidget(add_btn)

        mainlayout.addLayout(self.sublayout)
        self.setLayout(mainlayout)

        for i, tile_contents in enumerate(content.items()):
            # insert the boards
            self.insert_board(tile_contents, color[i])
Esempio n. 20
0
 def activate(self):
     """Adds items to scene and setup graphics effect.
     Called in the constructor and when re-adding the item to the project in the context of undo/redo.
     """
     scene = self._toolbox.ui.graphicsView.scene()
     scene.addItem(self)
     shadow_effect = QGraphicsDropShadowEffect()
     shadow_effect.setOffset(1)
     shadow_effect.setEnabled(False)
     self.setGraphicsEffect(shadow_effect)
Esempio n. 21
0
    def __init__(self, tile_contents, color, parent=None):
        super().__init__(parent)
        title_name, tile_items = tile_contents
        self.color = color
        self.setStyleSheet("QFrame{border: 0.5px solid #dddddd; "
                           "border-radius: 8px; background-color:white;}")
        shadow = QGraphicsDropShadowEffect(self,
                                           blurRadius=10,
                                           offset=5,
                                           color=QColor("lightgrey"))
        self.setGraphicsEffect(shadow)

        board = QVBoxLayout()
        board.setMargin(20)
        tile_title = NoteTile(title_name, self)
        tile_title.setPlaceholderText("Title here ...")
        tile_title.setStyleSheet(
            "border-style: none; font-size: 18px; font-weight: bold;")
        board.addWidget(tile_title)

        listwidget = BanListWidget(self)
        listwidget.setStyleSheet(TILE_STYLE.get(color, "black"))
        for tile in tile_items:
            listwidget.add_item(tile)

        board.addWidget(listwidget)

        btn_layout = QHBoxLayout()
        add_btn = QPushButton("+",
                              clicked=self.add_listitem,
                              toolTip="add tile")
        del_btn = QPushButton("-",
                              clicked=self.del_listitem,
                              toolTip="delete tile")
        context_btn = QPushButton("\u2261", toolTip="change color")
        context_btn.setMenu(self.context_menu())
        # context_btn.setStyleSheet('QPushButton:hover {color:#b5b3b3;} QPushButton::menu-indicator:hover {color:black;}')
        destory_btn = QPushButton("\u00D7",
                                  clicked=self.delete_board,
                                  toolTip="delete board")
        destory_btn.setStyleSheet("QPushButton:hover {color: red;}")
        btn_layout.addWidget(add_btn)
        btn_layout.addWidget(del_btn)
        btn_layout.addWidget(context_btn)
        btn_layout.addWidget(destory_btn)
        board.addLayout(btn_layout)

        self.setLayout(board)
    def __init__(self, toolbox, x, y, w, h, project_item, icon_file,
                 icon_color, background_color):
        """Base class for project item icons drawn in Design View.

        Args:
            toolbox (ToolBoxUI): QMainWindow instance
            x (float): Icon x coordinate
            y (float): Icon y coordinate
            w (float): Icon width
            h (float): Icon height
            project_item (ProjectItem): Item
            icon_file (str): Path to icon resource
            icon_color (QColor): Icon's color
            background_color (QColor): Background color
        """
        super().__init__()
        self._toolbox = toolbox
        self._project_item = project_item
        self._moved_on_scene = False
        self.renderer = QSvgRenderer()
        self.svg_item = QGraphicsSvgItem()
        self.colorizer = QGraphicsColorizeEffect()
        self.setRect(QRectF(x, y, w, h))  # Set ellipse coordinates and size
        self.text_font_size = 10  # point size
        # Make item name graphics item.
        name = project_item.name if project_item else ""
        self.name_item = QGraphicsSimpleTextItem(name)
        shadow_effect = QGraphicsDropShadowEffect()
        shadow_effect.setOffset(1)
        shadow_effect.setEnabled(False)
        self.setGraphicsEffect(shadow_effect)
        self.set_name_attributes()  # Set font, size, position, etc.
        # Make connector buttons
        self.connectors = dict(
            bottom=ConnectorButton(self, toolbox, position="bottom"),
            left=ConnectorButton(self, toolbox, position="left"),
            right=ConnectorButton(self, toolbox, position="right"),
        )
        # Make exclamation and rank icons
        self.exclamation_icon = ExclamationIcon(self)
        self.rank_icon = RankIcon(self)
        # Group the drawn items together by setting the background rectangle as the parent of other QGraphicsItems
        # NOTE: setting the parent item moves the items as one!
        self.name_item.setParentItem(self)
        for conn in self.connectors.values():
            conn.setParentItem(self)
        self.svg_item.setParentItem(self)
        self.exclamation_icon.setParentItem(self)
        self.rank_icon.setParentItem(self)
        brush = QBrush(background_color)
        self._setup(brush, icon_file, icon_color)
        # Add items to scene
        scene = self._toolbox.ui.graphicsView.scene()
        scene.addItem(self)
Esempio n. 23
0
 def __init__(self, toolbox, icon_file, icon_color, background_color):
     """
     Args:
         toolbox (ToolboxUI): QMainWindow instance
         icon_file (str): Path to icon resource
         icon_color (QColor): Icon's color
         background_color (QColor): Background color
     """
     super().__init__()
     self._toolbox = toolbox
     self.icon_file = icon_file
     self._moved_on_scene = False
     self.previous_pos = QPointF()
     self.current_pos = QPointF()
     self.icon_group = {self}
     self.renderer = QSvgRenderer()
     self.svg_item = QGraphicsSvgItem(self)
     self.colorizer = QGraphicsColorizeEffect()
     self.setRect(
         QRectF(-self.ITEM_EXTENT / 2, -self.ITEM_EXTENT / 2,
                self.ITEM_EXTENT, self.ITEM_EXTENT))
     self.text_font_size = 10  # point size
     # Make item name graphics item.
     self._name = ""
     self.name_item = QGraphicsSimpleTextItem(self._name, self)
     self.set_name_attributes()  # Set font, size, position, etc.
     # Make connector buttons
     self.connectors = dict(
         bottom=ConnectorButton(self, toolbox, position="bottom"),
         left=ConnectorButton(self, toolbox, position="left"),
         right=ConnectorButton(self, toolbox, position="right"),
     )
     # Make exclamation and rank icons
     self.exclamation_icon = ExclamationIcon(self)
     self.execution_icon = ExecutionIcon(self)
     self.rank_icon = RankIcon(self)
     brush = QBrush(background_color)
     self._setup(brush, icon_file, icon_color)
     shadow_effect = QGraphicsDropShadowEffect()
     shadow_effect.setOffset(1)
     shadow_effect.setEnabled(False)
     self.setGraphicsEffect(shadow_effect)
Esempio n. 24
0
    def __init__(self, tile_contents, color, parent=None):
        super().__init__(parent)
        title_name, tile_items = tile_contents
        self.color = color
        self.setObjectName("subBoardFrame")

        shadow = QGraphicsDropShadowEffect(self,
                                           blurRadius=10,
                                           offset=5,
                                           color=QColor("lightgrey"))
        self.setGraphicsEffect(shadow)

        board = QVBoxLayout()
        board.setMargin(20)
        tile_title = NoteTile(title_name, "boardEdit", self)
        tile_title.setPlaceholderText("Title here ...")

        board.addWidget(tile_title)

        self.listwidget = BanListWidget(self)
        self.listwidget.setStyleSheet(TILE_STYLE.get(color, "black"))
        for tile in tile_items:
            self.listwidget.add_item(tile)

        board.addWidget(self.listwidget)

        btn_layout = QHBoxLayout()
        add_btn = BanButton(
            "+",
            clicked=self.add_listitem,
            toolTip="add tile",
            objectName="boardBtn",
        )
        del_btn = BanButton(
            "-",
            clicked=self.del_listitem,
            toolTip="delete tile",
            objectName="boardBtn",
            shortcut=QKeySequence(Qt.Key_Backspace),
        )
        color_btn = BanButton(
            "\u2261",
            toolTip="change color",
            objectName="boardBtn_color",
            color=[("white", "#bdbdbd"), ("grey", "white")],
        )

        self.color_menu = self.context_menu()
        color_btn.setMenu(self.color_menu)
        color_btn.sizeSig.connect(self.menu_resize)

        destory_btn = BanButton(
            "\u00D7",
            clicked=self.delete_board,
            toolTip="delete board",
            objectName="boardBtn_des",
            color=[("white", "tomato"), ("white", "red")],
        )

        btn_layout.addWidget(add_btn)
        btn_layout.addWidget(del_btn)

        btn_layout.addWidget(color_btn)
        btn_layout.addWidget(destory_btn)
        board.addLayout(btn_layout)

        self.setLayout(board)
Esempio n. 25
0
class MainWindow(QtWidgets.QMainWindow):
    role_value = None
    DATA_PATH = 'D:\\SASTRA\Code\\Dean Mam Project\\assignment\\Data\\Medical_Records.csv'

    def __init__(self):
        print('Main init')
        QtWidgets.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.stackedWidget.setCurrentIndex(0)
        for i in RBACClass.permission_dict['Administrator']:
            self.ui.tableWidget.setColumnHidden(i, True)

        ## ==> MAXIMIZE RESTORE FUNCTION
        def maximize_restore():
            global GLOBAL_STATE
            status = GLOBAL_STATE

            # IF NOT MAXIMIZED
            if status == 0:
                self.showMaximized()

                # SET GLOBAL TO 1
                GLOBAL_STATE = 1

                # IF MAXIMIZED REMOVE MARGINS AND BORDER RADIUS
                self.ui.drop_shadow_frame.setContentsMargins(0, 0, 0, 0)
                self.ui.drop_shadow_frame.setStyleSheet(
                    "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(42, 44, 111, 255), stop:0.521368 rgba(28, 29, 73, 255)); border-radius: 0px;"
                )
                self.ui.maximize_btn.setToolTip("Restore")
            else:
                GLOBAL_STATE = 0
                self.showNormal()
                self.resize(self.width() + 1, self.height() + 1)
                self.ui.drop_shadow_frame.setContentsMargins(10, 10, 10, 10)
                self.ui.drop_shadow_frame.setStyleSheet(
                    "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(42, 44, 111, 255), stop:0.521368 rgba(28, 29, 73, 255)); border-radius: 10px;"
                )
                self.ui.maximize_btn.setToolTip("Maximize")

        ## ==> UI DEFINITIONS
        def uiDefinitions():

            # REMOVE TITLE BAR
            self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
            self.setAttribute(QtCore.Qt.WA_TranslucentBackground)

            # SET DROPSHADOW WINDOW
            self.shadow = QGraphicsDropShadowEffect(self)
            self.shadow.setBlurRadius(20)
            self.shadow.setXOffset(0)
            self.shadow.setYOffset(0)
            self.shadow.setColor(QColor(0, 0, 0, 100))

            # APPLY DROPSHADOW TO FRAME
            self.ui.drop_shadow_frame.setGraphicsEffect(self.shadow)

            # MAXIMIZE / RESTORE
            self.ui.maximize_btn.clicked.connect(lambda: maximize_restore())

            # MINIMIZE
            self.ui.minimize_btn.clicked.connect(lambda: self.showMinimized())

            # CLOSE
            self.ui.close_btn.clicked.connect(lambda: self.close())

            ## ==> CREATE SIZE GRIP TO RESIZE WINDOW
            self.sizegrip = QSizeGrip(self.ui.frame_grip)
            self.sizegrip.setStyleSheet(
                "QSizeGrip { width: 10px; height: 10px; margin: 5px } QSizeGrip:hover { background-color: rgb(50, 42, 94) }"
            )
            self.sizegrip.setToolTip("Resize Window")

        def rolePermission(role):
            for i in role:
                self.ui.tableWidget.setColumnHidden(i, False)

        # MOVE WINDOW
        def moveWindowMain(event):
            # RESTORE BEFORE MOVE
            if self.returnStatus() == 1:
                self.maximize_restore(self)

            # IF LEFT CLICK MOVE WINDOW
            if event.buttons() == Qt.LeftButton:
                self.move(self.pos() + event.globalPos() - self.dragPos)
                self.dragPos = event.globalPos()
                event.accept()

        def view_details():
            patient_id = self.ui.patientIdLineEdit_2.text()
            print(patient_id)
            self.ui.stackedWidget.setCurrentIndex(1)
            with open(MainWindow.DATA_PATH, 'r') as datafile:
                print('inside file')
                readData = csv.reader(datafile)
                rowValue = 0
                for row in readData:
                    print('inside row')
                    if row[1] == patient_id:
                        self.ui.tableWidget.insertRow(rowValue)
                        print(row[1], type(row[1]))
                        for i in MainWindow.role_value:
                            print('set')
                            self.ui.tableWidget.setItem(
                                rowValue, i, QTableWidgetItem(row[i]))
                        rowValue = rowValue + 1

        def go_back():
            self.ui.stackedWidget.setCurrentIndex(0)

        ## ==> SET UI DEFINITIONS
        uiDefinitions()

        print(MainWindow.role_value, "rolePerm")
        rolePermission(MainWindow.role_value)

        self.ui.viewDetailsPushButton_2.clicked.connect(view_details)
        self.ui.back_btn.clicked.connect(go_back)

        # SET TITLE BAR
        self.ui.title_bar_2.mouseMoveEvent = moveWindowMain

        ## SHOW ==> MAIN WINDOW
        ########################################################################
        self.show()

    ## RETURN STATUS IF WINDOWS IS MAXIMIZE OR RESTAURED
    def returnStatus(self):
        return GLOBAL_STATE

    ## APP EVENTS
    ########################################################################
    def mousePressEvent(self, event):
        self.dragPos = event.globalPos()
Esempio n. 26
0
class LoginWindow(QtWidgets.QWidget):
    def __init__(self):
        QtWidgets.QWidget.__init__(self)
        self.ui = Ui_Form()
        self.ui.setupUi(self)

        def uiDefinition():
            # REMOVE TITLE BAR
            self.shadow = QGraphicsDropShadowEffect(self)
            self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
            self.setAttribute(QtCore.Qt.WA_TranslucentBackground)

            # SET DROPSHADOW WINDOW
            self.shadow.setBlurRadius(20)
            self.shadow.setXOffset(0)
            self.shadow.setYOffset(0)
            self.shadow.setColor(QColor(0, 0, 0, 100))

            # APPLY DROPSHADOW TO FRAME
            self.ui.login_frame.setGraphicsEffect(self.shadow)

            # CLOSE
            self.ui.closePushButton.clicked.connect(lambda: self.close())

        # MOVE WINDOW
        def moveWindowLogin(event):
            # IF LEFT CLICK MOVE WINDOW
            if event.buttons() == Qt.LeftButton():
                self.move(self.pos() + event.globalPos() - self.dragPos)
                self.dragPos = event.globalPos()
                event.accept()

        def show_new_window():
            print(self.ui.userNameLineEdit.text(),
                  self.ui.passwordLineEdit.text())
            r = RBACClass()
            MainWindow.role_value = r.logon(
                UserName=self.ui.userNameLineEdit.text(),
                Password=self.ui.passwordLineEdit.text())
            print(MainWindow.role_value, "show")
            if MainWindow.role_value != None:
                print('here')
                self.close()
                w = MainWindow()
                w.show()
            else:
                print('no')
                self.ui.userNameLineEdit.setPlaceholderText('Try Again')
                self.ui.passwordLineEdit.setPlaceholderText('Try Again')

        # SET TITLE BAR
        self.ui.login_frame.mouseMoveEvent = moveWindowLogin
        self.ui.loginPushButton.clicked.connect(show_new_window)

        ## ==> SET UI DEFINITIONS
        uiDefinition()

        ## SHOW ==> MAIN WINDOW
        ########################################################################
        self.show()

    ## APP EVENTS
    ########################################################################
    def mousePressEvent(self, event):
        self.dragPos = event.globalPos()
Esempio n. 27
0
def set_shadow(QtWindow, button):
    shadow = QGraphicsDropShadowEffect(QtWindow)
    shadow.setBlurRadius(6)
    shadow.setOffset(3)
    shadow.setColor(QColor(0, 0, 0, 160))
    button.setGraphicsEffect(shadow)
class UIFunctions(MainWindow):

    ## ==> MAXIMIZE RESTORE FUNCTION
    def maximize_restore(self):
        global GLOBAL_STATE
        status = GLOBAL_STATE

        # IF NOT MAXIMIZED
        if status == 0:
            self.showMaximized()

            # SET GLOBAL TO 1
            GLOBAL_STATE = 1

            # IF MAXIMIZED REMOVE MARGINS AND BORDER RADIUS
            self.ui.drop_shadow_layout.setContentsMargins(0, 0, 0, 0)
            self.ui.drop_shadow_frame.setStyleSheet(
                "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(42, 44, 111, 255), stop:0.521368 rgba(28, 29, 73, 255)); border-radius: 0px;")
            self.ui.maximize_btn.setToolTip("Restore")
        else:
            GLOBAL_STATE = 0
            self.showNormal()
            self.resize(self.width() + 1, self.height() + 1)
            self.ui.drop_shadow_layout.setContentsMargins(10, 10, 10, 10)
            self.ui.drop_shadow_frame.setStyleSheet(
                "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(42, 44, 111, 255), stop:0.521368 rgba(28, 29, 73, 255)); border-radius: 10px;")
            self.ui.maximize_btn.setToolTip("Maximize")

    ## ==> UI DEFINITIONS
    def uiDefinitions(self):

        # REMOVE TITLE BAR
        self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)

        # SET DROPSHADOW WINDOW
        self.shadow = QGraphicsDropShadowEffect(self)
        self.shadow.setBlurRadius(20)
        self.shadow.setXOffset(0)
        self.shadow.setYOffset(0)
        self.shadow.setColor(QColor(0, 0, 0, 100))

        # APPLY DROPSHADOW TO FRAME
        self.ui.drop_shadow_frame.setGraphicsEffect(self.shadow)

        # MAXIMIZE / RESTORE
        self.ui.maximize_btn.clicked.connect(lambda: UIFunctions.maximize_restore(self))

        # MINIMIZE
        self.ui.minimize_btn.clicked.connect(lambda: self.showMinimized())

        # CLOSE
        self.ui.close_btn.clicked.connect(lambda: self.close())

        ## ==> CREATE SIZE GRIP TO RESIZE WINDOW
        self.sizegrip = QSizeGrip(self.ui.frame_grip)
        self.sizegrip.setStyleSheet(
            "QSizeGrip { width: 10px; height: 10px; margin: 5px } QSizeGrip:hover { background-color: rgb(50, 42, 94) }")
        self.sizegrip.setToolTip("Resize Window")

    ## RETURN STATUS IF WINDOWS IS MAXIMIZE OR RESTAURED
    def returnStatus(self):
        return GLOBAL_STATE
Esempio n. 29
0
class Central(QFrame):
    '''Initializes, styles, and connects the various classes'''

    def __init__(self):
        super().__init__()
        # Objects
        self.overallLayout = QVBoxLayout(self)
        self.contentLayout = QHBoxLayout()
        self.dropShadow = QGraphicsDropShadowEffect(self)
        self.boxManager = BoxManager.BoxManager()
        self.topBar = TopBar.TopBar()
        self.selectorArea = QFrame()
        self.selectorLayout = QVBoxLayout(self.selectorArea)
        self.folderArea = QFrame()
        self.folderLayout = QHBoxLayout(self.folderArea)
        self.folderList = FolderList.FolderList()
        self.folderBar = ScrollBar.ScrollBar(self.folderList)
        self.canvas = Canvas.Canvas(self.boxManager)
        self.imageArea = QFrame()
        self.imageList = ImageList.ImageList()
        self.imageLayout = QHBoxLayout(self.imageArea)
        self.imageBar = ScrollBar.ScrollBar(self.imageList)

        # Styling
        self.setStyleSheet('Central { background: transparent; }')
        self.overallLayout.setMargin(20)
        self.overallLayout.setSpacing(0)
        self.dropShadow.setOffset(QPointF(0,4))
        self.dropShadow.setColor(QColor(0,0,0,100))
        self.dropShadow.setBlurRadius(10)
        self.setGraphicsEffect(self.dropShadow)
        self.contentLayout.setAlignment(Qt.AlignCenter)
        self.contentLayout.setMargin(0)        
        self.contentLayout.setSpacing(0)
        self.selectorLayout.setMargin(0)
        self.selectorLayout.setSpacing(0)
        self.folderLayout.setMargin(0)
        self.folderLayout.setSpacing(0)
        self.imageLayout.setMargin(0)
        self.imageLayout.setSpacing(0)
        self.folderList.setVerticalScrollBar(self.folderBar)
        self.imageList.setVerticalScrollBar(self.imageBar)
        self.selectorArea.setMaximumWidth(400)
        self.selectorArea.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        # Layout
        self.folderLayout.addWidget(self.folderList)
        self.folderLayout.addSpacerItem(QSpacerItem(-7, 0))
        self.folderLayout.addWidget(self.folderBar)
        self.imageLayout.addWidget(self.imageList)
        self.imageLayout.addSpacerItem(QSpacerItem(-7, 0))
        self.imageLayout.addWidget(self.imageBar)
        self.selectorLayout.addWidget(self.folderArea, 15)
        self.selectorLayout.addWidget(self.imageArea, 85)
        self.contentLayout.addWidget(self.selectorArea, 30)
        self.contentLayout.addWidget(self.canvas, 70)
        self.overallLayout.addLayout(self.contentLayout)
        self.overallLayout.insertWidget(0, self.topBar)

        # Connections
        self.folderList.selectedFolderChanged.connect(self.handleSelectedFolderChanged)
        self.imageList.selectedImageChanged.connect(self.handleSelectedImageChanged)

    def handleSelectedFolderChanged(self, folder):
        self.imageList.populate(folder)
        self.canvas.changeImage(None)
        self.canvas.setMessage('Switching Folders - {}'.format(folder.data(role=Qt.DisplayRole)))
        self.topBar.setSelectedFolder(str(folder.data(role=Qt.UserRole+1)))
        self.topBar.setSelectedImage('')

    def handleSelectedImageChanged(self, image):
        self.canvas.changeImage(image)
        self.canvas.setMessage('Switching Images - {}'.format(image.data(role=Qt.DisplayRole)))
        self.topBar.setSelectedImage(str(image.data(role=Qt.DisplayRole)))
Esempio n. 30
0
class NodeInstance(QGraphicsItem):
    def __init__(self, params):
        super(NodeInstance, self).__init__()

        self.setFlags(QGraphicsItem.ItemIsSelectable
                      | QGraphicsItem.ItemIsMovable
                      | QGraphicsItem.ItemSendsScenePositionChanges)
        self.setAcceptHoverEvents(True)

        # GENERAL ATTRIBUTES

        # the constructor parameters are stored in a tuple to make the source code of custom NIs cleaner
        parent_node, flow, config = params

        self.parent_node = parent_node
        self.flow = flow
        self.movement_state = None
        self.movement_pos_from = None
        self.painted_once = False
        self.inputs = []
        self.outputs = []
        self.color = self.parent_node.color  # manipulated by self.animator
        # self.node_instance_painter = NodeInstancePainter(self)

        self.default_actions = {
            'remove': {
                'method': self.action_remove
            },
            'update shape': {
                'method': self.update_shape
            }
        }  # for context menus
        self.special_actions = {
        }  # only gets written in custom NodeInstance-subclasses
        self.personal_logs = []

        # 'initializing' will be set to False below. It's needed for the ports setup, to prevent shape updating stuff
        self.initializing = True

        self.temp_state_data = None
        self.init_config = config

        # UI
        self.shadow_effect = None
        self.width = -1
        self.height = -1

        self.title_label = TitleLabel(self)

        self.animator = NodeInstanceAnimator(self)  # needs self.title_label

        self.main_widget = None
        self.main_widget_proxy: FlowProxyWidget = None
        if self.parent_node.has_main_widget:
            self.main_widget = self.parent_node.main_widget_class(self)
            self.main_widget_proxy = FlowProxyWidget(self.flow)
            self.main_widget_proxy.setWidget(self.main_widget)

        # LOADING UI
        self.body_layout: QGraphicsLinearLayout = None
        self.inputs_layout: QGraphicsLinearLayout = None
        self.outputs_layout: QGraphicsLinearLayout = None
        self.layout: QGraphicsLinearLayout = self.setup_ui()
        self.widget = QGraphicsWidget(self)
        self.widget.setLayout(self.layout)

        # TOOLTIP
        if self.parent_node.description != '':
            self.setToolTip('<html><head/><body><p>' +
                            self.parent_node.description +
                            '</p></body></html>')
        self.setCursor(Qt.SizeAllCursor)

        # DESIGN THEME
        Design.flow_theme_changed.connect(self.theme_changed)

    def initialized(self):
        """All ports and the main widget get finally created here."""

        # LOADING CONFIG
        if self.init_config is not None:
            # self.setPos(config['position x'], config['position y'])
            self.setup_ports(self.init_config['inputs'],
                             self.init_config['outputs'])
            if self.main_widget:
                try:
                    self.main_widget.set_data(
                        self.init_config['main widget data'])
                except Exception as e:
                    print('Exception while setting data in',
                          self.parent_node.title,
                          'NodeInstance\'s main widget:', e,
                          ' (was this intended?)')

            self.special_actions = self.set_special_actions_data(
                self.init_config['special actions'])
            self.temp_state_data = self.init_config['state data']
        else:
            self.setup_ports()

        # LOADING DATA
        if self.temp_state_data is not None:
            try:
                self.set_data(self.temp_state_data)
            except Exception as e:
                print('Exception while setting data in',
                      self.parent_node.title, 'NodeInstance:', e,
                      ' (was this intended?)')

        self.initializing = False

        # No self.update_shape() here because for some reason, the bounding rect hasn't been initialized yet, so
        # self.update_shape() gets called when the item is being drawn the first time (see paint event in NI painter)
        # TODO: change that ^ once there is a solution for this: https://forum.qt.io/topic/117179/force-qgraphicsitem-to-update-immediately-wait-for-update-event

        self.update_design()  # load current design, update QGraphicsItem

        self.update()  # and finally update the NodeInstance once

    def setup_ui(self):
        """Creates the empty layouts for the NI's widget."""

        #   main layout
        layout = QGraphicsLinearLayout(Qt.Vertical)
        layout.setSpacing(10)

        if self.parent_node.design_style == 'extended':
            layout.addItem(self.title_label)
            layout.setAlignment(self.title_label, Qt.AlignTop)

        #   inputs
        self.inputs_layout = QGraphicsLinearLayout(Qt.Vertical)
        self.inputs_layout.setSpacing(2)

        #   outputs
        self.outputs_layout = QGraphicsLinearLayout(Qt.Vertical)
        self.outputs_layout.setSpacing(2)

        #   body
        self.body_layout = QGraphicsLinearLayout(Qt.Horizontal)

        self.body_layout.setSpacing(4)
        self.body_layout.addItem(self.inputs_layout)
        self.body_layout.setAlignment(self.inputs_layout,
                                      Qt.AlignVCenter | Qt.AlignLeft)
        self.body_layout.addStretch()
        self.body_layout.addItem(self.outputs_layout)
        self.body_layout.setAlignment(self.outputs_layout,
                                      Qt.AlignVCenter | Qt.AlignRight)

        if self.main_widget is not None:
            if self.parent_node.main_widget_pos == 'between ports':
                self.body_layout.insertItem(1, self.main_widget_proxy)
                self.body_layout.insertStretch(2)
                layout.addItem(self.body_layout)

            elif self.parent_node.main_widget_pos == 'under ports':
                layout.addItem(self.body_layout)
                layout.addItem(self.main_widget_proxy)
                layout.setAlignment(self.main_widget_proxy, Qt.AlignHCenter)
        else:
            layout.addItem(self.body_layout)

        return layout

    def rebuild_ui(self):
        """Due to some really strange and annoying behaviour of these QGraphicsWidgets, they don't want to shrink
        automatically when content is removed, they just stay large, even with a Minimum SizePolicy. I didn't find a
        way around that yet, so for now I have to recreate the whole layout and make sure the widget uses the smallest
        size possible."""

        # if I don't manually remove the ports from the layouts,
        # they get deleted when setting the widget's layout to None below
        for inp in self.inputs:
            self.inputs_layout.removeAt(0)
        for out in self.outputs:
            self.outputs_layout.removeAt(0)

        self.layout = self.setup_ui()  # recreate layout

        # forcefully making the widget shrink
        self.widget.setLayout(None)
        self.widget.resize(self.widget.minimumSize())

        self.widget.setLayout(self.layout)

        # add inputs to new layout
        for inp in self.inputs:
            self.add_input_to_layout(inp)
        for out in self.outputs:
            self.add_output_to_layout(out)

    #                        __                             _    __     __
    #              ____ _   / /  ____ _   ____     _____   (_)  / /_   / /_     ____ ___
    #             / __ `/  / /  / __ `/  / __ \   / ___/  / /  / __/  / __ \   / __ `__ \
    #            / /_/ /  / /  / /_/ /  / /_/ /  / /     / /  / /_   / / / /  / / / / / /
    #            \__,_/  /_/   \__, /   \____/  /_/     /_/   \__/  /_/ /_/  /_/ /_/ /_/
    #                         /____/

    def update(self, input_called=-1, output_called=-1):
        """This is the method used to activate a NodeInstance. Note that this signature shadows the update() method from
        QGraphicsItem used to graphically update a QGraphicsItem which can be accessed via
        QGraphicsItem.update(self)."""

        if Design.animations_enabled:
            self.animator.start()

        Debugger.debug('update in', self.parent_node.title, 'on input',
                       input_called)
        try:
            self.update_event(input_called)
        except Exception as e:
            Debugger.debug('EXCEPTION IN', self.parent_node.title, 'NI:', e)

    def update_event(self, input_called=-1):
        """Gets called when an input received a signal. This is where the magic begins in subclasses."""

        pass

    def input(self, index):
        """Returns the value of a data input.
        If the input is connected, the value of the connected output is used:
        If not, the value of the widget is used."""

        Debugger.debug('input called in', self.parent_node.title, 'NI:', index)
        return self.inputs[index].get_val()

    def exec_output(self, index):
        """Executes an execution output, sending a signal to all connected execution inputs causing the connected
        NIs to update."""
        self.outputs[index].exec()

    def set_output_val(self, index, val):
        """Sets the value of a data output.
        self.data_outputs_updated() has to be called manually after all values are set."""

        if not self.flow.viewport_update_mode.sync:  # asynchronous viewport updates
            vp = self.flow.viewport()
            vp.repaint(self.flow.mapFromScene(self.sceneBoundingRect()))

        self.outputs[index].set_val(val)

    def data_outputs_updated(self):
        """(outdated!) Sends update signals to all data outputs causing connected NIs to update."""

        Debugger.debug('updating data outputs in', self.parent_node.title)
        for o in self.outputs:
            if o.type_ == 'data':
                o.updated_val()
        Debugger.debug('data outputs in', self.parent_node.title, 'updated')

    def remove_event(self):
        """Method to stop all threads in hold of the NI itself."""

        pass

    #                                 _
    #              ____ _   ____     (_)
    #             / __ `/  / __ \   / /
    #            / /_/ /  / /_/ /  / /
    #            \__,_/  / .___/  /_/
    #                   /_/
    #
    # all algorithm-unrelated api methods:

    #   LOGGING
    def new_log(self, title):
        """Requesting a new personal Log. Handy method for subclasses."""
        new_log = self.flow.parent_script.logger.new_log(self, title)
        self.personal_logs.append(new_log)
        return new_log

    def disable_personal_logs(self):
        """Disables personal Logs. They remain visible unless the user closes them via the appearing button."""
        for log in self.personal_logs:
            log.disable()

    def enable_personal_logs(self):
        """Resets personal Logs to normal state (hiding close button, changing style sheet)."""
        for log in self.personal_logs:
            log.enable()

    def log_message(self, message: str, target='global'):
        """Access to global_tools Script Logs ('global' or 'error')."""
        self.flow.parent_script.logger.log_message(message, target)

    # SHAPE
    def update_shape(self):
        """Causes recompilation of the whole shape."""
        # if not self.initializing:   # just to make sure
        #     self.rebuild_ui()       # (hopefully) temporary fix -> see rebuild_ui() docstring

        if self.main_widget is not None:  # maybe the main_widget got resized
            self.main_widget_proxy.setMaximumSize(self.main_widget.size())
            self.widget.adjustSize()
            self.widget.adjustSize()

        self.body_layout.invalidate()
        self.layout.invalidate()
        self.layout.activate()
        # very essential; repositions everything in case content has changed (inputs/outputs/widget)

        if self.parent_node.design_style == 'minimalistic':

            # making it recompute its true minimumWidth here
            self.widget.adjustSize()

            if self.layout.minimumWidth() < self.title_label.width + 15:
                self.layout.setMinimumWidth(self.title_label.width + 15)
                self.layout.activate()

        self.width = self.boundingRect().width()
        self.height = self.boundingRect().height()
        rect = QRectF(QPointF(-self.width / 2, -self.height / 2),
                      QPointF(self.width / 2, self.height / 2))
        self.widget.setPos(rect.left(), rect.top())

        if not self.parent_node.design_style == 'extended':
            self.title_label.setPos(
                QPointF(-self.title_label.boundingRect().width() / 2,
                        -self.title_label.boundingRect().height() / 2))

        self.flow.viewport().update()

    # PORTS
    def create_new_input(self,
                         type_,
                         label,
                         widget_name=None,
                         widget_pos='under',
                         pos=-1,
                         config=None):
        """Creates and adds a new input. Handy for subclasses."""
        Debugger.debug('create_new_input called')
        pi = InputPortInstance(self,
                               type_,
                               label,
                               config_data=config,
                               widget_name=widget_name,
                               widget_pos=widget_pos)
        if pos < -1:
            pos += len(self.inputs)
        if pos == -1:
            self.inputs.append(pi)
            self.add_input_to_layout(pi)
        else:
            self.inputs.insert(pos, pi)
            self.insert_input_into_layout(pos, pi)

        if not self.initializing:
            self.update_shape()
            self.update()

    def add_input_to_layout(self, i):
        if self.inputs_layout.count() > 0:
            self.inputs_layout.addStretch()
        self.inputs_layout.addItem(i)
        self.inputs_layout.setAlignment(i, Qt.AlignLeft)

    def insert_input_into_layout(self, index, i):
        self.inputs_layout.insertItem(index * 2,
                                      i)  # *2 because of the stretches
        self.inputs_layout.setAlignment(i, Qt.AlignLeft)
        if len(self.inputs) > 1:
            self.inputs_layout.insertStretch(
                index * 2 + 1)  # *2+1 because of the stretches, too

    def delete_input(self, i):
        """Disconnects and removes input. Handy for subclasses."""
        inp: InputPortInstance = None
        if type(i) == int:
            inp = self.inputs[i]
        elif type(i) == InputPortInstance:
            inp = i

        for cpi in inp.connected_port_instances:
            self.flow.connect_gates(inp.gate, cpi.gate)

        # for some reason, I have to remove all widget items manually from the scene too. setting the items to
        # ownedByLayout(True) does not work, I don't know why.
        self.scene().removeItem(inp.gate)
        self.scene().removeItem(inp.label)
        if inp.proxy is not None:
            self.scene().removeItem(inp.proxy)

        self.inputs_layout.removeItem(inp)
        self.inputs.remove(inp)

        # just a temporary workaround for the issues discussed here:
        # https://forum.qt.io/topic/116268/qgraphicslayout-not-properly-resizing-to-change-of-content
        self.rebuild_ui()

        if not self.initializing:
            self.update_shape()
            self.update()

    def create_new_output(self, type_, label, pos=-1):
        """Creates and adds a new output. Handy for subclasses."""

        pi = OutputPortInstance(self, type_, label)
        if pos < -1:
            pos += len(self.outputs)
        if pos == -1:
            self.outputs.append(pi)
            self.add_output_to_layout(pi)
        else:
            self.outputs.insert(pos, pi)
            self.insert_output_into_layout(pos, pi)

        if not self.initializing:
            self.update_shape()
            self.update()

    def add_output_to_layout(self, o):
        if self.outputs_layout.count() > 0:
            self.outputs_layout.addStretch()
        self.outputs_layout.addItem(o)
        self.outputs_layout.setAlignment(o, Qt.AlignRight)

    def insert_output_into_layout(self, index, o):
        self.outputs_layout.insertItem(index * 2,
                                       o)  # *2 because of the stretches
        self.outputs_layout.setAlignment(o, Qt.AlignRight)
        if len(self.outputs) > 1:
            self.outputs_layout.insertStretch(
                index * 2 + 1)  # *2+1 because of the stretches, too

    def delete_output(self, o):
        """Disconnects and removes output. Handy for subclasses."""
        out: OutputPortInstance = None
        if type(o) == int:
            out = self.outputs[o]
        elif type(o) == OutputPortInstance:
            out = o

        for cpi in out.connected_port_instances:
            self.flow.connect_gates(out.gate, cpi.gate)

        # see delete_input() for info!
        self.scene().removeItem(out.gate)
        self.scene().removeItem(out.label)

        self.outputs_layout.removeItem(out)
        self.outputs.remove(out)

        # just a temporary workaround for the issues discussed here:
        # https://forum.qt.io/topic/116268/qgraphicslayout-not-properly-resizing-to-change-of-content
        self.rebuild_ui()

        if not self.initializing:
            self.update_shape()
            self.update()

    # GET, SET DATA
    def get_data(self):
        """
        This method gets subclassed and specified. If the NI has states (so, the behavior depends on certain values),
        all these values must be stored in JSON-able format in a dict here. This dictionary will be used to reload the
        node's state when loading a project or pasting copied/cut nodes in the Flow (the states get copied too), see
        self.set_data(self, data) below.
        Unfortunately, I can't use pickle or something like that due to PySide2 which runs on C++, not Python.
        :return: Dictionary representing all values necessary to determine the NI's current state
        """
        return {}

    def set_data(self, data):
        """
        If the NI has states, it's state should get reloaded here according to what was previously provided by the same
        class in get_data(), see above.
        :param data: Dictionary representing all values necessary to determine the NI's current state
        """
        pass

    @staticmethod
    def get_default_stylesheet():
        """Handy method for subclasses to access the application window's stylesheet for UI content."""
        return Design.ryven_stylesheet

    # VARIABLES

    def get_vars_handler(self):
        return self.flow.parent_script.variables_handler

    def get_var_val(self, name):
        return self.get_vars_handler().get_var_val(name)

    def set_var_val(self, name, val):
        return self.get_vars_handler().set_var(name, val)

    def register_var_receiver(self, name, method):
        self.get_vars_handler().register_receiver(self, name, method)

    def unregister_var_receiver(self, name):
        self.get_vars_handler().unregister_receiver(self, name)

    # --------------------------------------------------------------------------------------
    # UI STUFF ----------------------------------------

    def theme_changed(self, new_theme):
        self.title_label.theme_changed(new_theme)
        self.update_design()

    def update_design(self):
        """Loads the shadow effect option and causes redraw with active theme."""

        if Design.node_instance_shadows_shown:
            self.shadow_effect = QGraphicsDropShadowEffect()
            self.shadow_effect.setXOffset(12)
            self.shadow_effect.setYOffset(12)
            self.shadow_effect.setBlurRadius(20)
            self.shadow_effect.setColor(QColor('#2b2b2b'))
            self.setGraphicsEffect(self.shadow_effect)
        else:
            self.setGraphicsEffect(None)

        self.title_label.update_design()
        # print(self.title_label.color)
        self.animator.reload_values()

        QGraphicsItem.update(self)

    def boundingRect(self):
        # remember: (0, 0) shall be the NI's center!
        rect = QRectF()
        w = self.layout.geometry().width()
        h = self.layout.geometry().height()
        rect.setLeft(-w / 2)
        rect.setTop(-h / 2)
        rect.setWidth(w)
        rect.setHeight(h)
        return rect

    #   PAINTING
    def paint(self, painter, option, widget=None):
        """All painting is done by NodeInstancePainter"""

        # in order to access a meaningful geometry of GraphicsWidget contents in update_shape(), the paint event
        # has to be called once. See here:
        # https://forum.qt.io/topic/117179/force-qgraphicsitem-to-update-immediately-wait-for-update-event/4
        if not self.painted_once:
            self.title_label.update_design()  # also necessary
            self.update_shape()

        # self.node_instance_painter.paint(painter, option, self.color, self.width, self.height, self.boundingRect(),
        #                                  Design.flow_theme, widget)
        Design.flow_theme.node_inst_painter.paint_NI(
            design_style=self.parent_node.design_style,
            painter=painter,
            option=option,
            c=self.color,
            w=self.width,
            h=self.height,
            bounding_rect=self.boundingRect(),
            title_rect=self.title_label.boundingRect())

        self.painted_once = True

    def get_context_menu(self):
        menu = QMenu(self.flow)

        for a in self.get_actions(self.get_extended_default_actions(),
                                  menu):  # menu needed for 'parent'
            if type(a) == NodeInstanceAction:
                menu.addAction(a)
            elif type(a) == QMenu:
                menu.addMenu(a)

        menu.addSeparator()

        actions = self.get_actions(self.special_actions, menu)
        for a in actions:  # menu needed for 'parent'
            if type(a) == NodeInstanceAction:
                menu.addAction(a)
            elif type(a) == QMenu:
                menu.addMenu(a)

        return menu

    def itemChange(self, change, value):
        """This method ensures that all connections, selection borders etc. that get drawn in the Flow are constantly
        redrawn during a NI drag. Should get disabled when running in performance mode - not implemented yet."""

        if change == QGraphicsItem.ItemPositionChange:
            if Design.performance_mode == 'pretty':
                self.flow.viewport().update()
            if self.movement_state == MovementEnum.mouse_clicked:
                self.movement_state = MovementEnum.position_changed

        return QGraphicsItem.itemChange(self, change, value)

    def hoverEnterEvent(self, event):
        self.title_label.set_NI_hover_state(hovering=True)
        QGraphicsItem.hoverEnterEvent(self, event)

    def hoverLeaveEvent(self, event):
        self.title_label.set_NI_hover_state(hovering=False)
        QGraphicsItem.hoverLeaveEvent(self, event)

    def mousePressEvent(self, event):
        """Used for Moving-Commands in Flow - may be replaced later with a nicer determination of a moving action."""
        self.movement_state = MovementEnum.mouse_clicked
        self.movement_pos_from = self.pos()
        return QGraphicsItem.mousePressEvent(self, event)

    def mouseReleaseEvent(self, event):
        """Used for Moving-Commands in Flow - may be replaced later with a nicer determination of a moving action."""
        if self.movement_state == MovementEnum.position_changed:
            self.flow.selected_components_moved(self.pos() -
                                                self.movement_pos_from)
        self.movement_state = None
        return QGraphicsItem.mouseReleaseEvent(self, event)

    # ACTIONS
    def get_extended_default_actions(self):
        actions_dict = self.default_actions.copy()
        for index in range(len(self.inputs)):
            inp = self.inputs[index]
            if inp.type_ == 'exec':
                actions_dict['exec input ' + str(index)] = {
                    'method': self.action_exec_input,
                    'data': {
                        'input index': index
                    }
                }
        return actions_dict

    def action_exec_input(self, data):
        self.update(data['input index'])

    def get_actions(self, actions_dict, menu):
        actions = []

        for k in actions_dict:
            v_dict = actions_dict[k]
            try:
                method = v_dict['method']
                data = None
                try:
                    data = v_dict['data']
                except KeyError:
                    pass
                action = NodeInstanceAction(k, menu, data)
                action.triggered_with_data.connect(
                    method)  # see NodeInstanceAction for explanation
                action.triggered_without_data.connect(
                    method)  # see NodeInstanceAction for explanation
                actions.append(action)
            except KeyError:
                action_menu = QMenu(k, menu)
                sub_actions = self.get_actions(v_dict, action_menu)
                for a in sub_actions:
                    action_menu.addAction(a)
                actions.append(action_menu)

        return actions

    def action_remove(self):
        self.flow.remove_node_instance_triggered(self)

    def get_special_actions_data(self, actions):
        cleaned_actions = actions.copy()
        for key in cleaned_actions:
            v = cleaned_actions[key]
            if type(v) == M:  # callable(v):
                cleaned_actions[key] = v.method_name
            elif callable(v):
                cleaned_actions[key] = v.__name__
            elif type(v) == dict:
                cleaned_actions[key] = self.get_special_actions_data(v)
            else:
                cleaned_actions[key] = v
        return cleaned_actions

    def set_special_actions_data(self, actions_data):
        actions = {}
        for key in actions_data:
            if type(actions_data[key]) != dict:
                if key == 'method':
                    try:
                        actions['method'] = M(getattr(self, actions_data[key]))
                    except AttributeError:  # outdated method referenced
                        pass
                elif key == 'data':
                    actions['data'] = actions_data[key]
            else:
                actions[key] = self.set_special_actions_data(actions_data[key])
        return actions

    # PORTS
    def setup_ports(self, inputs_config=None, outputs_config=None):
        if not inputs_config and not outputs_config:
            for i in range(len(self.parent_node.inputs)):
                inp = self.parent_node.inputs[i]
                self.create_new_input(
                    inp.type_,
                    inp.label,
                    widget_name=self.parent_node.inputs[i].widget_name,
                    widget_pos=self.parent_node.inputs[i].widget_pos)

            for o in range(len(self.parent_node.outputs)):
                out = self.parent_node.outputs[o]
                self.create_new_output(out.type_, out.label)
        else:  # when loading saved NIs, the port instances might not be synchronised to the parent's ports anymore
            for inp in inputs_config:
                has_widget = inp['has widget']

                self.create_new_input(
                    inp['type'],
                    inp['label'],
                    widget_name=inp['widget name'] if has_widget else None,
                    widget_pos=inp['widget position'] if has_widget else None,
                    config=inp['widget data'] if has_widget else None)

            for out in outputs_config:
                self.create_new_output(out['type'], out['label'])

    def get_input_widget_class(self, widget_name):
        """Returns a reference to the widget class of a given name for instantiation."""
        custom_node_input_widget_classes = self.flow.parent_script.main_window.custom_node_input_widget_classes
        widget_class = custom_node_input_widget_classes[
            self.parent_node][widget_name]
        return widget_class

    def add_input_to_scene(self, i):
        self.flow.scene().addItem(i.gate)
        self.flow.scene().addItem(i.label)
        if i.widget:
            self.flow.scene().addItem(i.proxy)

    def del_and_remove_input_from_scene(self, i_index):
        i = self.inputs[i_index]
        for p in self.inputs[i_index].connected_port_instances:
            self.flow.connect_gates(i.gate, p.gate)

        self.flow.scene().removeItem(i.gate)
        self.flow.scene().removeItem(i.label)
        if i.widget:
            self.flow.scene().removeItem(i.proxy)
            i.widget.remove_event()
        self.inputs.remove(i)

    def add_output_to_scene(self, o):
        self.flow.scene().addItem(o.gate)
        self.flow.scene().addItem(o.label)

    def del_and_remove_output_from_scene(self, o_index):
        o = self.outputs[o_index]
        for p in self.outputs[o_index].connected_port_instances:
            self.flow.connect_gates(o.gate, p.gate)

        self.flow.scene().removeItem(o.gate)
        self.flow.scene().removeItem(o.label)
        self.outputs.remove(o)

    # GENERAL
    def about_to_remove_from_scene(self):
        """Called from Flow when the NI gets removed from the scene
        to stop all running threads and disable personal logs."""

        if self.main_widget:
            self.main_widget.remove_event()
        self.remove_event()

        self.disable_personal_logs()

    def is_active(self):
        for i in self.inputs:
            if i.type_ == 'exec':
                return True
        for o in self.outputs:
            if o.type_ == 'exec':
                return True
        return False

    def has_main_widget(self):
        """Might be used later in CodePreview_Widget to enable not only showing the NI's class but also it's
        main_widget's class."""
        return self.main_widget is not None

    def get_input_widgets(self):
        """Might be used later in CodePreview_Widget to enable not only showing the NI's class but its input widgets'
        classes."""
        input_widgets = []
        for i in range(len(self.inputs)):
            inp = self.inputs[i]
            if inp.widget is not None:
                input_widgets.append({i: inp.widget})
        return input_widgets

    def get_json_data(self):
        """Returns all metadata of the NI including position, package etc. in a JSON-able dict format.
        Used to rebuild the Flow when loading a project."""

        # general attributes
        node_instance_dict = {
            'parent node title': self.parent_node.title,
            'parent node type': self.parent_node.type_,
            'parent node package': self.parent_node.package,
            'parent node description': self.parent_node.description,
            'position x': self.pos().x(),
            'position y': self.pos().y()
        }
        if self.main_widget:
            node_instance_dict['main widget data'] = self.main_widget.get_data(
            )

        node_instance_dict['state data'] = self.get_data()
        node_instance_dict['special actions'] = self.get_special_actions_data(
            self.special_actions)

        # inputs
        node_instance_inputs_list = []
        for i in self.inputs:
            input_dict = i.get_json_data()
            node_instance_inputs_list.append(input_dict)
        node_instance_dict['inputs'] = node_instance_inputs_list

        # outputs
        node_instance_outputs_list = []
        for o in self.outputs:
            output_dict = o.get_json_data()
            node_instance_outputs_list.append(output_dict)
        node_instance_dict['outputs'] = node_instance_outputs_list

        return node_instance_dict