Пример #1
0
    def get_manager_button(self):
        """Returns QToolButton for managing the toolbar"""

        button = QToolButton(self)
        button.setText("Add/remove toolbar icons")
        button.setMenu(ToolbarManagerMenu(self))
        button.setIcon(Icon.menu_manager)
        button.setFixedWidth(button.height() / 3)
        button.setPopupMode(QToolButton.InstantPopup)

        return button
Пример #2
0
class ToolOptionsPad(QWidget):

    """ An on-canvas toolbox widget. I'm dubbing widgets that 'float' 
    on top of the canvas '(lily) pads' for the time being :) """

    def __init__(self, mdiArea):
        super(ToolOptionsPad, self).__init__(mdiArea)
        self.setObjectName("toolOptionsPad")
        # self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.setWindowFlags(
            Qt.WindowStaysOnTopHint | 
            Qt.FramelessWindowHint
            )
        self.setLayout(QVBoxLayout())
        self.layout().setContentsMargins(4,4,4,4)

        # Members to hold a borrowed widget and it's original parent docker for returning
        self.widget = None
        self.widgetDocker = None
        self.container = ToolOptionsContainer()
        
        # Visibility toggle
        self.btnHide = QToolButton()
        self.btnHide.setIcon(Application.icon("light_visible"))
        self.btnHide.setIconSize(QSize(12,12))
        self.btnHide.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum)
        self.btnHide.clicked.connect(self.toggleWidgetVisible)
        self.btnHide.setStyleSheet("""
            QToolButton {
                background-color: #80000000;
                border: none;
                border-radius: 4px;
            }
            
            QToolButton:checked {
                background-color: #aa306fa8;
            }
            
            QToolButton:hover {
                background-color: #1c1c1c;
            }
            
            QToolButton:pressed {
                background-color: #53728e;
            }
            """)

        self.layout().addWidget(self.btnHide)#, 0, Qt.AlignRight)


    def closeEvent(self, e):
        """Since the plugins works by borrowing the actual docker 
        widget we need to ensure its returned upon closing the pad"""
        self.returnDocker()
        return super().closeEvent(e)


    def paintEvent(self, e):
        """Needed to resize the Pad if the user decides to 
        change the icon size of the toolbox"""
        self.adjustToView()
        return super().paintEvent(e)


    def borrowDocker(self, docker):
        """Borrow a docker widget from Krita's existing list of dockers and 
        returns True. Returns False if invalid widget was passed. """

        # Does requested widget exist?
        if isinstance(docker, QDockWidget) and docker.widget():
            # Return any previous widget to its original docker
            self.returnDocker()
                
            self.widgetDocker = docker
            self.widget = docker.widget()

            # Because I'm forced to use "setFixedSize" to resize the tool options
            # it needs to be put in a container, otherwise it's going to break if/when
            # returned to its original docker. Manipulate the container; not the widget.
            self.container = ToolOptionsContainer()
            self.container.layout().addWidget(self.widget)

            self.layout().addWidget(self.container, 0, Qt.AlignRight) 
            self.adjustToView()        
            
            return True
            
        return False


    def returnDocker(self):
        """Return the borrowed docker to it's original QDockWidget"""
        # Ensure there's a widget to return
        if self.widget:
            self.widgetDocker.setWidget(self.widget)
            self.widget = None
            self.widgetDocker = None


    def adjustToView(self):
        """Adjust the position and size of the Pad to that of the active View."""
        view = self.activeView()
        if view:
            
            self.resizeToView() # Resize first because the x-position is dependant on correct width.

            # pos = self.parentWidget().mapFromGlobal(view.mapToGlobal(QPoint(view.width() - self.parentWidget().width(), 0))) # Move to top of QMdiArea. Only suitable for 'AdjustToSubwindows' mode.
            pos = self.parentWidget().mapFromGlobal(view.mapToGlobal(QPoint(view.width() - self.width(), 0))) # Move to top left corner of current view. Hacky, but works!
            self.move(pos)
    
    def resizeToView(self): # The Tool Options widget is a nightmare to resize :)
        """Resize the Pad to an appropriate size that fits within the subwindow."""
        view = self.activeView()

        if view and self.widget.isVisible():
            # We start with the tool options sizeHint as a goal size and then
            # shrink it down if necessary to fit inside the view.
            containerSize = self.widget.widget().sizeHint()

            # I don't like all these magic numbers (And repeteition) but I honestly don't know what they
            # correspond to either. Margins, I suppose, but then why is one of the numbers 14
            # when the margins are all 4?

            if view.height() < containerSize.height() + self.btnHide.height() + 14:
                containerSize.setHeight(view.height() - self.btnHide.height() - 14)

            if view.width() < containerSize.width() + 8:
                containerSize.setWidth(view.width() - 8)
            
            self.container.setFixedSize(containerSize)

            # Once the tool options container is an appropriate size, resize the
            # Pad widget to it's appropriate sizes
            padSize = self.sizeHint()
            if view.height() < padSize.height():
                padSize.setHeight(view.height())

            if view.width() < padSize.width():
                padSize.setWidth(view.width())
            
            self.setFixedSize(padSize)

        elif not self.widget.isVisible():
            # Resize the widget to the size of the button + some extra height for the hidden widget I guess?

            # I just don't know what these numbers are, or why I can't use the 
            # button's own sizeHint. The result also varies if something else
            # about the layout varies.
            self.setFixedSize(23, 54) 


    def activeView(self):
        """Get the View widget of the active subwindow."""
        subWin = self.parentWidget().activeSubWindow()
        
        if subWin:
            for child in subWin.children(): 
                if 'view' in child.objectName(): # Grab the View from the active tab/sub-window
                    return child


    def toggleWidgetVisible(self, value=None):

        if not value:
            value = not self.widget.isVisible()
            
        self.widget.setVisible(value)
        self.resizeToView()  
Пример #3
0
class HomeRecommendedItem(QWidget, fc_home_recommended_item):
    """
    This class represents a HomeRecommendedItem widget which is shown on the home page. This widget can either show
    a channel or a torrent.
    """
    def __init__(self, parent):
        QWidget.__init__(self, parent)
        fc_home_recommended_item.__init__(self)

        self.setupUi(self)

        self.show_torrent = True
        self.torrent_info = None
        self.channel_info = None
        self.download_uri = None
        self.dialog = None

        # Create the category label, shown on cells that display a torrent on the home page
        self.category_label = QLabel(self)
        self.category_label.setFixedHeight(24)
        self.category_label.setSizePolicy(
            QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed))
        self.category_label.setStyleSheet("""
        border: 2px solid white;
        border-radius: 12px;
        background-color: transparent;
        color: white;
        padding-left: 4px;
        padding-right: 4px;
        font-weight: bold;
        """)
        self.category_label.move(QPoint(6, 6))
        self.category_label.show()

        # Create the dark overlay and download button over the thumbnail on hover
        self.dark_overlay = QWidget(self)
        self.dark_overlay.setStyleSheet(
            "background-color: rgba(0, 0, 0, 0.65);")
        self.dark_overlay.hide()

        self.download_button = QToolButton(self)
        self.download_button.setFixedSize(QSize(40, 40))
        self.download_button.setStyleSheet("""
        QToolButton {
            background-color: transparent;
            border: 2px solid white;
            border-radius: 20px;
        }

        QToolButton::hover {
            border: 2px solid #B5B5B5;
        }
        """)
        self.download_button.setIcon(QIcon(get_image_path('downloads.png')))
        self.download_button.setIconSize(QSize(18, 18))
        self.download_button.clicked.connect(self.on_download_button_clicked)
        self.download_button.hide()

    def on_download_button_clicked(self):
        if not self.torrent_info:
            return
        self.download_uri = (u"magnet:?xt=urn:btih:%s&dn=%s" %
                             (self.torrent_info["infohash"],
                              self.torrent_info['name'])).encode('utf-8')
        self.window().start_download_from_uri(self.download_uri)

    def update_with_torrent(self, torrent):
        if not torrent:
            return
        self.show_torrent = True
        self.torrent_info = torrent
        self.thumbnail_widget.initialize(torrent["name"], HOME_ITEM_FONT_SIZE)
        self.main_label.setText(torrent["name"])
        self.category_label.setText(torrent["category"].lower() if (
            "category" in torrent and torrent["category"]) else 'other')
        self.category_label.adjustSize()
        self.category_label.setHidden(False)
        self.setCursor(Qt.ArrowCursor)
        self.detail_label.setText("Size: " +
                                  format_size(torrent.get("size", 0)))

    def update_with_channel(self, channel):
        if not channel:
            return
        self.show_torrent = False
        self.channel_info = channel
        self.thumbnail_widget.initialize(channel["name"], HOME_ITEM_FONT_SIZE)

        self.main_label.setText(channel["name"])
        self.detail_label.setText("%d torrents" % channel["torrents"])
        self.category_label.setHidden(True)
        self.setCursor(Qt.PointingHandCursor)

    def enterEvent(self, _):
        if self.show_torrent:
            self.dark_overlay.resize(self.thumbnail_widget.size())
            self.dark_overlay.show()
            self.download_button.move(
                (self.thumbnail_widget.width() - self.download_button.width())
                / 2, (self.thumbnail_widget.height() -
                      self.download_button.height()) / 2)
            self.download_button.show()

    def leaveEvent(self, _):
        self.dark_overlay.hide()
        self.download_button.hide()
Пример #4
0
class HomeRecommendedItem(QWidget, fc_home_recommended_item):
    """
    This class represents a HomeRecommendedItem widget which is shown on the home page. This widget can either show
    a channel or a torrent.
    """

    def __init__(self, parent):
        QWidget.__init__(self, parent)
        fc_home_recommended_item.__init__(self)

        self.setupUi(self)

        self.show_torrent = True
        self.torrent_info = None
        self.channel_info = None
        self.download_uri = None
        self.dialog = None

        # Create the category label, shown on cells that display a torrent on the home page
        self.category_label = QLabel(self)
        self.category_label.setFixedHeight(24)
        self.category_label.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed))
        self.category_label.setStyleSheet("""
        border: 2px solid white;
        border-radius: 12px;
        background-color: transparent;
        color: white;
        padding-left: 4px;
        padding-right: 4px;
        font-weight: bold;
        """)
        self.category_label.move(QPoint(6, 6))
        self.category_label.show()

        # Create the dark overlay and download button over the thumbnail on hover
        self.dark_overlay = QWidget(self)
        self.dark_overlay.setStyleSheet("background-color: rgba(0, 0, 0, 0.65);")
        self.dark_overlay.hide()

        self.download_button = QToolButton(self)
        self.download_button.setFixedSize(QSize(40, 40))
        self.download_button.setStyleSheet("""
        QToolButton {
            background-color: transparent;
            border: 2px solid white;
            border-radius: 20px;
        }

        QToolButton::hover {
            border: 2px solid #B5B5B5;
        }
        """)
        self.download_button.setIcon(QIcon(get_image_path('downloads.png')))
        self.download_button.setIconSize(QSize(18, 18))
        self.download_button.clicked.connect(self.on_download_button_clicked)
        self.download_button.hide()

    def on_download_button_clicked(self):
        gui_settings = self.window().gui_settings
        self.download_uri = quote_plus((u"magnet:?xt=urn:btih:%s&dn=%s" %
                                        (self.torrent_info["infohash"], self.torrent_info['name'])).encode('utf-8'))

        if get_gui_setting(gui_settings, "ask_download_settings", True, is_bool=True):
            self.dialog = StartDownloadDialog(self.window().stackedWidget, self.download_uri, self.torrent_info["name"])
            self.dialog.button_clicked.connect(self.on_start_download_action)
            self.dialog.show()
        else:
            self.window().perform_start_download_request(self.download_uri,
                                                         get_gui_setting(gui_settings, "default_anonymity_enabled",
                                                                         True, is_bool=True),
                                                         get_gui_setting(gui_settings, "default_safeseeding_enabled",
                                                                         True, is_bool=True),
                                                         self.window().tribler_settings['downloadconfig']['saveas'],
                                                         [], 0)

    def on_start_download_action(self, action):
        if action == 1:
            self.window().perform_start_download_request(self.download_uri,
                                                         self.dialog.dialog_widget.anon_download_checkbox.isChecked(),
                                                         self.dialog.dialog_widget.safe_seed_checkbox.isChecked(),
                                                         self.dialog.dialog_widget.destination_input.text(),
                                                         self.dialog.get_selected_files(),
                                                         self.dialog.dialog_widget.files_list_view.topLevelItemCount())

        self.dialog.request_mgr.cancel_request()
        self.dialog.setParent(None)
        self.dialog = None

    def update_with_torrent(self, torrent):
        self.show_torrent = True
        self.torrent_info = torrent
        self.thumbnail_widget.initialize(torrent["name"], HOME_ITEM_FONT_SIZE)
        self.main_label.setText(torrent["name"])
        self.category_label.setText(torrent["category"])
        self.category_label.adjustSize()
        self.category_label.setHidden(False)
        self.setCursor(Qt.ArrowCursor)
        self.detail_label.setText("Size: " + format_size(torrent["size"]))

    def update_with_channel(self, channel):
        self.show_torrent = False
        self.channel_info = channel
        self.thumbnail_widget.initialize(channel["name"], HOME_ITEM_FONT_SIZE)

        self.main_label.setText(channel["name"])
        self.detail_label.setText("Updated " + pretty_date(channel["modified"]))
        self.category_label.setHidden(True)
        self.setCursor(Qt.PointingHandCursor)

    def enterEvent(self, _):
        if self.show_torrent:
            self.dark_overlay.resize(self.thumbnail_widget.size())
            self.dark_overlay.show()
            self.download_button.move((self.thumbnail_widget.width() - self.download_button.width()) / 2,
                                      (self.thumbnail_widget.height() - self.download_button.height()) / 2)
            self.download_button.show()

    def leaveEvent(self, _):
        self.dark_overlay.hide()
        self.download_button.hide()
Пример #5
0
class HomeRecommendedItem(QWidget, fc_home_recommended_item):
    """
    This class represents a HomeRecommendedItem widget which is shown on the home page. This widget can either show
    a channel or a torrent.
    """

    def __init__(self, parent):
        QWidget.__init__(self, parent)
        fc_home_recommended_item.__init__(self)

        self.setupUi(self)

        self.show_torrent = True
        self.torrent_info = None
        self.channel_info = None
        self.download_uri = None
        self.dialog = None

        # Create the category label, shown on cells that display a torrent on the home page
        self.category_label = QLabel(self)
        self.category_label.setFixedHeight(24)
        self.category_label.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed))
        self.category_label.setStyleSheet("""
        border: 2px solid white;
        border-radius: 12px;
        background-color: transparent;
        color: white;
        padding-left: 4px;
        padding-right: 4px;
        font-weight: bold;
        """)
        self.category_label.move(QPoint(6, 6))
        self.category_label.show()

        # Create the dark overlay and download button over the thumbnail on hover
        self.dark_overlay = QWidget(self)
        self.dark_overlay.setStyleSheet("background-color: rgba(0, 0, 0, 0.65);")
        self.dark_overlay.hide()

        self.download_button = QToolButton(self)
        self.download_button.setFixedSize(QSize(40, 40))
        self.download_button.setStyleSheet("""
        QToolButton {
            background-color: transparent;
            border: 2px solid white;
            border-radius: 20px;
        }

        QToolButton::hover {
            border: 2px solid #B5B5B5;
        }
        """)
        self.download_button.setIcon(QIcon(get_image_path('downloads.png')))
        self.download_button.setIconSize(QSize(18, 18))
        self.download_button.clicked.connect(self.on_download_button_clicked)
        self.download_button.hide()

    def on_download_button_clicked(self):
        if not self.torrent_info:
            return
        self.download_uri = (u"magnet:?xt=urn:btih:%s&dn=%s" %
                             (self.torrent_info["infohash"], self.torrent_info['name'])).encode('utf-8')
        self.window().start_download_from_uri(self.download_uri)

    def update_with_torrent(self, torrent):
        if not torrent:
            return
        self.show_torrent = True
        self.torrent_info = torrent
        self.thumbnail_widget.initialize(torrent["name"], HOME_ITEM_FONT_SIZE)
        self.main_label.setText(torrent["name"])
        self.category_label.setText(torrent["category"].lower())
        self.category_label.adjustSize()
        self.category_label.setHidden(False)
        self.setCursor(Qt.ArrowCursor)
        self.detail_label.setText("Size: " + format_size(torrent["size"]))

    def update_with_channel(self, channel):
        if not channel:
            return
        self.show_torrent = False
        self.channel_info = channel
        self.thumbnail_widget.initialize(channel["name"], HOME_ITEM_FONT_SIZE)

        self.main_label.setText(channel["name"])
        self.detail_label.setText("Updated " + pretty_date(channel["modified"]))
        self.category_label.setHidden(True)
        self.setCursor(Qt.PointingHandCursor)

    def enterEvent(self, _):
        if self.show_torrent:
            self.dark_overlay.resize(self.thumbnail_widget.size())
            self.dark_overlay.show()
            self.download_button.move((self.thumbnail_widget.width() - self.download_button.width()) / 2,
                                      (self.thumbnail_widget.height() - self.download_button.height()) / 2)
            self.download_button.show()

    def leaveEvent(self, _):
        self.dark_overlay.hide()
        self.download_button.hide()
Пример #6
0
class CollapsibleSplitter(QSplitter):
    def __init__(self, parent, *args):
        super(CollapsibleSplitter, self).__init__(parent, *args)
        self.parent = parent
        self.setOpaqueResize(True)
        self.minDistanceToEdge = 20  # 到边缘的最小距离
        self.splitterState = SplitterState.expanded
        self.bSplitterButton = False
        self.setHandleWidth(10)
        self.bExpandParentForm = False

        self.splitterMoved.connect(self.splitterMoveHandle)

    @pyqtProperty(bool)
    def SplitterButton(self):
        return self.bSplitterButton

    @SplitterButton.setter
    def SplitterButton(self, value):
        self.bSplitterButton = value

    @pyqtProperty(bool)
    def ExpandParentForm(self):
        return self.bExpandParentForm

    @ExpandParentForm.setter
    def ExpandParentForm(self, value):
        self.bExpandParentForm = value

    @pyqtProperty(SplitterState)
    def Stretch(self):
        return self.splitterState

    @Stretch.setter
    def Stretch(self, value):
        self.splitterState = value

    @pyqtProperty(Dock)
    def Dock(self):
        return self.dock

    @Dock.setter
    def Dock(self, value):
        self.dock = value

    @pyqtProperty(QWidget)
    def WidgetToHide(self):
        return self.widgetToHide

    @WidgetToHide.setter
    def WidgetToHide(self, value: QWidget):
        self.widgetToHide = value

    def showEvent(self, a0: QShowEvent) -> None:
        self.setupUi()

    def setupUi(self):
        self.handlePos = self.sizes()

        if self.widget(0).objectName() == self.widgetToHide.objectName():
            self.otherWidget = self.widget(1)
        else:
            self.otherWidget = self.widget(0)

        self.hide_num = self.indexOf(self.widgetToHide)

        #  控制最小边缘距离
        if self.dock == Dock.up or self.dock == Dock.down:
            self.setOrientation(Qt.Vertical)
            self.widgetToHide.setMinimumHeight(self.minDistanceToEdge)
            self.otherWidget.setMinimumHeight(self.minDistanceToEdge)
        else:
            self.setOrientation(Qt.Horizontal)
            self.widgetToHide.setMinimumWidth(self.minDistanceToEdge)
            self.otherWidget.setMinimumWidth(self.minDistanceToEdge)

        self.widgetToHide.setMouseTracking(True)
        self.otherWidget.setMouseTracking(True)
        self.setMouseTracking(True)

        if self.splitterState == SplitterState.collapsed:
            self.handleSplitterButton(SplitterState=SplitterState.expanded)

        if self.bSplitterButton:
            self.button = QToolButton(self.parentWidget())
            self.button.clicked.connect(
                lambda: self.handleSplitterButton(self.splitterState))

    def eventFilter(self, obj: QObject, event: QEvent):
        print(event.type())
        if event.type() == QEvent.MouseMove:
            print("move")
        if event.type() == QEvent.KeyPress:
            print("key presss")
        if event.type() == QEvent.MouseButtonPress:
            print("press")

        return super().eventFilter(obj, event)

    def handleSplitterButton(self, SplitterState=SplitterState.expanded):
        # if not all(self.splitter.sizes()):
        #     self.splitter.setSizes([1, 1])
        self.setChildrenCollapsible(True)

        # print(self.sizes())
        if SplitterState == SplitterState.expanded:
            self.handlePos = self.sizes()  # 记下展开时的位置,如果再次展开回到这个位置

            if self.bExpandParentForm:
                if self.dock == Dock.left or self.dock == Dock.right:
                    self.hideLen = self.widgetToHide.width()
                    self.window().resize(self.window().width() - self.hideLen,
                                         self.window().height())
                else:
                    self.hideLen = self.widgetToHide.height()
                    self.window().resize(self.window().width(),
                                         self.window().height() - self.hideLen)

            if self.dock == Dock.up and self.dock == Dock.left:
                self.setSizes([0, 1])
            else:
                self.setSizes([1, 0])

            self.splitterState = SplitterState.collapsed
        else:
            if not self.bExpandParentForm:
                self.setSizes(self.handlePos)  # 1, 0
            else:
                if self.dock == Dock.up or self.dock == Dock.left:
                    otherLen = self.sizes()[1]
                else:
                    otherLen = self.sizes()[0]

                if self.dock == Dock.left or self.dock == Dock.right:
                    # otherLen = self.sizes()[1] if hide_num == 0 else self.sizes()[0]
                    self.window().resize(self.window().width() + self.hideLen,
                                         self.window().height())
                else:
                    self.window().resize(self.window().width(),
                                         self.window().height() + self.hideLen)

                if self.dock == Dock.up or self.dock == Dock.left:
                    self.setSizes([self.hideLen, otherLen])
                else:
                    self.setSizes([otherLen, self.hideLen])

            self.splitterState = SplitterState.expanded

        if self.bSplitterButton:
            self.setBtnIcon()
            self.setBtnPos()

        # if self.splitterState == SplitterState.collapsed:
        #     self.setEnabled(False)
        # else:
        #     self.setEnabled(True)

    def splitterMoveHandle(self, pos, index):
        if self.orientation() == Qt.Horizontal:
            w = self.width()
        else:
            w = self.height()
        if pos > self.minDistanceToEdge or pos < w - self.minDistanceToEdge:
            self.setChildrenCollapsible(False)

            # if self.splitterState == SplitterState.collapsed:
            #     hide_num = self.indexOf(self.widgetToHide)
            #     if self.Dock == Dock.up or self.Dock == Dock.left:
            #         self.setSizes([1, 0]) if hide_num == 0 else self.setSizes([0, 1])
            #     else:
            #         self.setSizes([0, 1]) if hide_num == 0 else self.setSizes([1, 0])

        if self.bSplitterButton:
            self.setBtnPos()

    def createButton(self, width, height):
        self.button.setFocusPolicy(Qt.NoFocus)
        self.button.setMinimumSize(5, 15)
        self.button.resize(width, height)

        if self.dock == Dock.up:
            self.button.setArrowType(Qt.UpArrow)
        elif self.dock == Dock.down:
            self.button.setArrowType(Qt.DownArrow)
        elif self.dock == Dock.left:
            self.button.setArrowType(Qt.LeftArrow)
        elif self.dock == Dock.right:
            self.button.setArrowType(Qt.RightArrow)
        self.setBtnPos()

    def setBtnIcon(self):
        if self.button.arrowType() == Qt.LeftArrow:
            self.button.setArrowType(Qt.RightArrow)
        elif self.button.arrowType() == Qt.RightArrow:
            self.button.setArrowType(Qt.LeftArrow)
        elif self.button.arrowType() == Qt.UpArrow:
            self.button.setArrowType(Qt.DownArrow)
        elif self.button.arrowType() == Qt.DownArrow:
            self.button.setArrowType(Qt.UpArrow)

    def setBtnPos(self):
        if (self.dock == Dock.up and self.splitterState == SplitterState.expanded) or \
                (self.dock == Dock.down and self.splitterState == SplitterState.collapsed):
            self.button.move(
                (self.widgetToHide.width() - self.button.width()) / 2,
                self.handle(1).pos().y() - self.button.height())
        elif (self.dock == Dock.up and self.splitterState == SplitterState.collapsed) or \
                (self.dock == Dock.down and self.splitterState == SplitterState.expanded):
            self.button.move(
                (self.widgetToHide.width() - self.button.width()) / 2,
                self.handle(1).pos().y() + self.handle(1).height())
        elif (self.dock == Dock.right and self.splitterState == SplitterState.expanded) or \
                (self.dock == Dock.left and self.splitterState == SplitterState.collapsed):
            self.button.move(
                self.handle(1).pos().x() + self.handle(1).width(),
                (self.widgetToHide.height() - self.button.height()) / 2)
        elif (self.dock == Dock.right and self.splitterState == SplitterState.collapsed) or \
                (self.dock == Dock.left and self.splitterState == SplitterState.expanded):
            self.button.move(
                self.handle(1).pos().x() - self.button.width(),
                (self.widgetToHide.height() - self.button.height()) / 2)

    # def resizeEvent(self, a0: QResizeEvent):
    #     self.resize(a0.size())

    def createHandle(self):
        handle = SplitterHandle(self.orientation(), self)
        return handle
Пример #7
0
class PictureEditor(QWidget):
    modeChanged = pyqtSignal(EditMode)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.bkimage = QPixmap('./ui/png/tile.png')
        self.photo = None
        self.currentZoom = 1.0
        self.offset = QPoint(0, 0)
        self.mode = EditMode.IDLE
        # overlays
        self.mesOverlay = MesOverlay(self)
        self.mesOverlay.doneCallBack = self._onMeasureDone
        self.roiOverlay = RoiOverlay(self)
        self.contOverlay = ContOverlay(self)
        self.contOverlay.freehandDone = self._onFreeHandDone
        self.overlays = [self.mesOverlay, self.roiOverlay, self.contOverlay]
        # eingebettete button
        self.btnContPlus = QToolButton(self)
        self.btnContPlus.setIcon(qta.icon('fa5s.plus', color='white'))
        self.btnContPlus.setStyleSheet("background-color: #19232D")
        self.btnContPlus.clicked.connect(self._onAddCountClicked)
        self.btnContPlus.hide()
        self.btnContMinus = QToolButton(self)
        self.btnContMinus.setIcon(qta.icon('fa5s.minus', color='white'))
        self.btnContMinus.setStyleSheet("background-color: #19232D")
        self.btnContMinus.clicked.connect(self._onRemoveCountClicked)
        self.btnContMinus.hide()
        self.btnFindCont = QPushButton('Find Contours', self)
        self.btnFindCont.clicked.connect(self._onFindContClicked)
        self.btnFindCont.hide()

        mngr = QtGui.qApp.sessionManager
        mngr.contourChanged.connect(self.updateContour)
        self.setMouseTracking(True)
        self.show()

    def setPhoto(self, photo, roi=None):
        self.mesOverlay.reset()
        self.photo = photo
        if roi is not None:
            if roi.isValid():
                self.roiOverlay.imageRoi = roi
            else:
                w = photo.width()
                h = photo.height()
                self.roiOverlay.imageRoi = QRect(w / 4, h / 4, w / 2, h / 2)
            self.setMode(EditMode.ROI)
        else:
            self.update()

    def setMode(self, mode):
        if mode == self.mode:
            return
        newoverlay = self.getOverlay(mode)
        oldoverlay = self.getOverlay(self.mode)
        if oldoverlay is not None:
            oldoverlay.leave()
        if newoverlay is not None:
            newoverlay.enter()
        self.btnContPlus.hide()
        self.btnContMinus.hide()
        self.btnFindCont.setVisible(mode == EditMode.ROI)
        self.mode = mode
        self.modeChanged.emit(mode)
        self.update()

    @pyqtSlot(QPolygonF)
    def updateContour(self, cont):
        self.contOverlay.contour = cont
        self.update()

    def paintEvent(self, event):
        painter = QPainter()
        painter.begin(self)
        crc = self.rect()
        painter.fillRect(crc, QBrush(self.bkimage))
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setRenderHint(QPainter.HighQualityAntialiasing)
        if self.photo is not None:
            srcrect = self.photo.rect()
            destrect = self.transform().mapRect(srcrect)
            painter.drawPixmap(destrect, self.photo, srcrect)
            painter.fillRect(crc, QBrush(QColor(0, 0, 0, 40)))
        if self.mode == EditMode.IDLE:
            # alle duerfen zeichen
            for overlay in self.overlays:
                overlay.render(painter)
        else:
            self.getOverlay(self.mode).render(painter)
        painter.end()

    def event(self, event):
        proc = False
        overlay = self.getOverlay(self.mode)
        if overlay is not None:
            if overlay.routeEvent(event):
                proc = True
        if self.mode == EditMode.ROI:
            # update pos von fund contour button
            imroi = self.roiOverlay.imageRoi.normalized()
            br = self.transform().map(imroi.bottomRight())
            self.btnFindCont.move(br.x() - self.btnFindCont.width(),
                                  br.y() + 8)
        if proc is True:
            return True
        else:
            return super().event(event)

    def mousePressEvent(self, event):
        if event.button() == Qt.MiddleButton:
            self._mousePressedPos = event.pos() - self.offset

    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.MiddleButton:
            self.offset = event.pos() - self._mousePressedPos
            self.update()

    def wheelEvent(self, event):
        if (event.angleDelta().y() > 0) and self.currentZoom < 3.0:
            fct = 1.10
        elif self.currentZoom > 1.0:
            fct = 1 / 1.10
        else:
            fct = 1.0
        self.currentZoom = self.currentZoom * fct
        self.update()

    def transform(self) -> QTransform:
        if self.photo is not None:
            srcrc = self.photo.rect()
            destrc = self.rect()
            trfshift = _translate(srcrc, destrc, self.offset)
            trfscale = _scale(srcrc, destrc, self.currentZoom)
            return trfscale * trfshift
        else:
            return QTransform()

    def _onMeasureDone(self):
        overlay = self.mesOverlay
        mngr = QtGui.qApp.sessionManager
        dlg = uic.loadUi('./ui/mesauredistdialog.ui')
        dlg.lineEdit.setValidator(QtGui.QIntValidator(0, 10000))
        res = dlg.exec_()
        if res == QDialog.Accepted and len(dlg.lineEdit.text()) > 0:
            overlay.lengthText = dlg.lineEdit.text() + 'mm'
            mngr.ppmm = overlay.lineLength() / float(dlg.lineEdit.text())
            if dlg.btnAcc.isChecked():
                mngr.sizeFlags = session.SizeFlags.ACCURATELY
            elif dlg.btnLessAcc.isChecked():
                mngr.sizeFlags = session.SizeFlags.LESS_ACCURATE
            elif dlg.btnInAcc.isChecked():
                mngr.sizeFlags = session.SizeFlags.INACCURATE
            else:
                mngr.sizeFlags = session.SizeFlags.UNKNOWN
        else:
            mngr.ppmm = None
            mngr.sizeFlags = session.SizeFlags.UNKNOWN
            overlay.reset()

        self.setMode(EditMode.IDLE)

    def _onFreeHandDone(self, mousePos):
        offs = 10
        h = self.btnContPlus.height()
        self.btnContMinus.move(mousePos.x() + offs, mousePos.y() + offs - h)
        self.btnContPlus.move(mousePos.x() + offs, mousePos.y() + offs)
        self.btnContPlus.show()
        self.btnContMinus.show()

    def _onAddCountClicked(self):
        sm = QtGui.qApp.sessionManager
        sm.addForeground(self.contOverlay.freeHandPath)
        self.contOverlay.freeHandPath.clear()
        self.btnContPlus.hide()
        self.btnContMinus.hide()
        self.update()

    def _onRemoveCountClicked(self):
        sm = QtGui.qApp.sessionManager
        sm.removeForeground(self.contOverlay.freeHandPath)
        self.contOverlay.freeHandPath.clear()
        self.btnContPlus.hide()
        self.btnContMinus.hide()
        self.update()

    def _onFindContClicked(self):
        self.setMode(EditMode.FG)
        sm = QtGui.qApp.sessionManager
        sm.findForeground(self.roiOverlay.imageRoi)

    def getOverlay(self, mode):
        o = {
            EditMode.IDLE: None,
            EditMode.MEASURE: self.mesOverlay,
            EditMode.ROI: self.roiOverlay,
            EditMode.FG: self.contOverlay
        }
        return o[mode]