Esempio n. 1
0
class AlgorithmChoose(QWidget):
    finished = Signal()
    started = Signal()
    result = Signal(SegmentationResult)
    value_changed = Signal()
    progress_signal = Signal(str, int)
    algorithm_changed = Signal(str)

    def __init__(
        self, settings: BaseSettings, algorithms: typing.Dict[str, typing.Type[SegmentationAlgorithm]], parent=None
    ):
        super().__init__(parent)
        self.settings = settings
        self.algorithms = algorithms
        settings.algorithm_changed.connect(self.updated_algorithm)
        self.stack_layout = QStackedLayout()
        self.algorithm_choose = QComboBox()
        self.algorithm_dict: typing.Dict[str, BaseAlgorithmSettingsWidget] = {}
        self.algorithm_choose.currentTextChanged.connect(self.change_algorithm)
        self.add_widgets_to_algorithm()

        self.settings.image_changed.connect(self.image_changed)
        # self.setMinimumWidth(370)

        self.setContentsMargins(0, 0, 0, 0)
        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.algorithm_choose)
        layout.addLayout(self.stack_layout)
        self.setLayout(layout)

    def add_widgets_to_algorithm(self):
        self.algorithm_choose.blockSignals(True)
        self.algorithm_choose.clear()
        for name, val in self.algorithms.items():
            self.algorithm_choose.addItem(name)
            widget = InteractiveAlgorithmSettingsWidget(self.settings, name, val, [])
            self.algorithm_dict[name] = widget
            widget.algorithm_thread.execution_done.connect(self.result.emit)
            widget.algorithm_thread.finished.connect(self.finished.emit)
            widget.algorithm_thread.started.connect(self.started.emit)
            widget.algorithm_thread.progress_signal.connect(self.progress_signal.emit)
            widget.values_changed.connect(self.value_changed.emit)
            self.stack_layout.addWidget(widget)
        name = self.settings.get("current_algorithm", "")
        self.algorithm_choose.blockSignals(False)
        if name:
            self.algorithm_choose.setCurrentText(name)

    def reload(self, algorithms=None):
        if algorithms is not None:
            self.algorithms = algorithms
        for _ in range(self.stack_layout.count()):
            widget: InteractiveAlgorithmSettingsWidget = self.stack_layout.takeAt(0).widget()
            widget.algorithm_thread.execution_done.disconnect()
            widget.algorithm_thread.finished.disconnect()
            widget.algorithm_thread.started.disconnect()
            widget.algorithm_thread.progress_signal.disconnect()
            widget.values_changed.disconnect()
        self.algorithm_dict = {}
        self.add_widgets_to_algorithm()

    def updated_algorithm(self):
        self.change_algorithm(
            self.settings.last_executed_algorithm,
            self.settings.get(f"algorithms.{self.settings.last_executed_algorithm}"),
        )

    def recursive_get_values(self):
        result = {}
        for key, widget in self.algorithm_dict.items():
            result[key] = widget.recursive_get_values()
        self.settings.set("algorithm_widget_state", update(self.settings.get("algorithm_widget_state", dict), result))
        return result

    def change_algorithm(self, name, values: dict = None):
        self.settings.set("current_algorithm", name)
        widget = self.stack_layout.currentWidget()
        self.blockSignals(True)
        if name != widget.name:
            widget = self.algorithm_dict[name]
            self.stack_layout.setCurrentWidget(widget)
            widget.image_changed(self.settings.image)
            if hasattr(widget, "set_mask") and hasattr(self.settings, "mask"):
                widget.set_mask(self.settings.mask)
        elif values is None:
            self.blockSignals(False)
            return
        if values is not None:
            widget.set_values(values)
        self.algorithm_choose.setCurrentText(name)
        self.blockSignals(False)
        self.algorithm_changed.emit(name)

    def image_changed(self):
        current_widget: InteractiveAlgorithmSettingsWidget = self.stack_layout.currentWidget()
        if hasattr(self.settings, "mask") and hasattr(current_widget, "change_mask"):
            current_widget.change_mask()
        current_widget.image_changed(self.settings.image)

    def mask_changed(self):
        current_widget: InteractiveAlgorithmSettingsWidget = self.stack_layout.currentWidget()
        if hasattr(self.settings, "mask") and hasattr(current_widget, "change_mask"):
            current_widget.change_mask()

    def current_widget(self) -> InteractiveAlgorithmSettingsWidget:
        return self.stack_layout.currentWidget()

    def current_parameters(self) -> SegmentationProfile:
        widget = self.current_widget()
        return SegmentationProfile("", widget.name, widget.get_values())

    def get_info_text(self):
        return self.current_widget().algorithm_thread.get_info_text()
Esempio n. 2
0
class TabContainer(AbstractContainer):
    dockMove = Signal(object, object, object)

    class Point(object):
        def __init__(self, x, y):
            self.__x = x
            self.__y = y

        def x(self):
            return self.__x

        def y(self):
            return self.__y

    def __init__(self, bench, parent_container):
        """ Container which layouts its child items on stacked layout and provides a tab bar.

        :param bench:
        :param parent_container:
        """
        super(TabContainer, self).__init__(bench, parent_container)

        self.setAcceptDrops(True)
        self.refDropRegions = None
        self.absDropRegions = None
        self.overlay = DropOverlay(self)

        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(0)
        if CONFIG.debug_layout:
            self.layout.setContentsMargins(2, 16, 2, 2)
        self.setLayout(self.layout)

        self._tabbar = TabHeader()
        self.layout.addWidget(self._tabbar)

        self._dockstack = QStackedLayout()
        self._dockstack.setContentsMargins(0, 0, 0, 0)
        self._dockstack.setSpacing(0)
        self.layout.addLayout(self._dockstack)

    def activateTab(self, uid):
        _log.debug("Activating tab for dock: {}".format(uid))

        for d in self.flatDockList:
            if d.uid == uid:
                self._dockstack.setCurrentWidget(d)
                d.tab.setActive(True)
            else:
                d.tab.setActive(False)

    def closeChild(self, uid):
        _log.debug("Closing dock: {}".format(uid))

        was_active = False
        for d in self.flatDockList:
            if d.uid == uid:
                _log.debug("Removing dock: {}".format(d))

                was_active = d.tab.active

                d.tab.setParent(None)
                d.tab._dock = None
                d.parentContainer = None
                d.close()
                d.deleteLater()
                d.setParent(None)

        self.contentModified.emit()
        if self._dockstack.count() == 0:
            # Container is empty, close and propagate
            self.closing.emit(self._uid)
        elif was_active:
            dock = self.flatDockList[0]
            self.activateTab(dock.uid)

    @property
    def flatDockList(self):
        return [
            self._dockstack.itemAt(k).widget()
            for k in range(self._dockstack.count())
        ]

    @property
    def docks(self):
        return self.flatDockList

    def addItem(self, index, item):

        # _config.debug check
        if not isinstance(item, Dock):
            raise BenchException("Misuse")

        item.parentContainer = self
        item.closing.connect(self.closeChild)
        item.activated.connect(self.activateTab)

        self._tabbar.addTab(index, item)
        self._dockstack.insertWidget(index, item)
        self.activateTab(item.uid)

        item.setVisible(True)
        item.tab.setVisible(True)

    @classmethod
    def __checkEventMimeTypeData(cls, event):
        """ Checks the drag events MIME type, and that at least two dockbench items on the area.

        :param event: drag event / drop event
        :return: true when the MIME type can be handled
        """
        if not event.mimeData().hasFormat(MIME_TYPE):
            event.ignore()
            return False

        event.accept()
        return True

    def dragEnterEvent(self, event):
        _log.debug("TabContainer: Drag enter event")
        if not self.__checkEventMimeTypeData(event):
            return

        data = event.mimeData().data(MIME_TYPE).data()
        dock_uid = pickle.loads(data)
        _log.debug("ETID: {}".format(dock_uid))

        for d in self.flatDockList:
            if d.uid == dock_uid and len(self.flatDockList) == 1:
                _log.debug("Tab in container")
                event.ignore()
                return

        if self.rect().width() < 200 and self.rect().height() < 200:
            _log.debug("To less widget left...")
            event.ignore()
            return

        if self.overlay.isHidden():
            _log.debug("Drop overlay")
            self.overlay.raise_()
            self.overlay.show()
            w = self._dockstack.currentWidget()
            pos = w.mapTo(self, QPoint(0, 0))
            rect = QRect(pos.x(), pos.y(), w.width(), w.height())
            self.overlay.setGeometry(rect)

            xc = pos.x() + w.width() / 2.0
            yc = pos.y() + w.height() / 2.0

            self.refDropRegions = {
                TabContainer.Point(xc - 34, yc): Placement.LEFT,
                TabContainer.Point(xc + 34, yc): Placement.RIGHT,
                TabContainer.Point(xc, yc - 34): Placement.TOP,
                TabContainer.Point(xc, yc + 34): Placement.BOTTOM,
                TabContainer.Point(xc, yc): Placement.TAB,
            }
            self.absDropRegions = {
                TabContainer.Point(xc - 68, yc): Placement.LEFT,
                TabContainer.Point(xc + 68, yc): Placement.RIGHT,
                TabContainer.Point(xc, yc - 68): Placement.TOP,
                TabContainer.Point(xc, yc + 68): Placement.BOTTOM,
            }

    def dragMoveEvent(self, event):
        if not self.__checkEventMimeTypeData(event):
            return

        pos = event.pos()
        x = pos.x()
        y = pos.y()

        for region in self.refDropRegions:
            if abs(region.x() - x) <= 12 and abs(region.y() - y) <= 12:
                _log.debug("Drop ref over: {}".format(
                    self.refDropRegions[region]))
                event.accept()
                self.overlay.setActiveDropRegion(self.refDropRegions[region])
                return

        for region in self.absDropRegions:
            if abs(region.x() - x) <= 12 and abs(region.y() - y) <= 12:
                _log.debug("Drop abs over: {}".format(
                    self.absDropRegions[region]))
                event.accept()
                self.overlay.setActiveDropRegion(self.absDropRegions[region],
                                                 True)
                return

        self.overlay.setActiveDropRegion(None)
        event.ignore()

    def dragLeaveEvent(self, event):
        _log.debug("TabContainer: Drag leave event")

        if not self.overlay.isHidden():
            self.overlay.hide()

            self.refDropRegions = None
            self.absDropRegions = None

    def dropEvent(self, event):
        _log.debug("TabContainer: Drop event")

        if not self.__checkEventMimeTypeData(event):
            event.ignore()
            return

        data = event.mimeData().data(MIME_TYPE).data()
        dock_uid = pickle.loads(data)
        _log.debug("ETID: {}".format(dock_uid))

        pos = event.pos()
        x = pos.x()
        y = pos.y()

        for region in self.refDropRegions:
            if abs(region.x() - x) <= 12 and abs(region.y() - y) <= 12:
                _log.debug("Drop ref over: {}".format(
                    self.refDropRegions[region]))

                ref = self._dockstack.currentWidget()
                # self.dockMove.emit(dock_uid, self.refDropRegions[region], ref.uid)
                self._bench.dockMove(dock_uid, self.refDropRegions[region],
                                     ref.uid)
                break

        if self.absDropRegions is not None:
            for region in self.absDropRegions:
                if abs(region.x() - x) <= 12 and abs(region.y() - y) <= 12:
                    _log.debug("Drop abs over: {}".format(
                        self.absDropRegions[region]))

                    # self.dockMove.emit(dock_uid, self.absDropRegions[region], None)
                    self._bench.dockMove(dock_uid, self.absDropRegions[region],
                                         None)
                    break

        if not self.overlay.isHidden():
            self.overlay.hide()

            self.refDropRegions = None
            self.absDropRegions = None

    def saveLayout(self):
        layout = super(TabContainer, self).saveLayout()

        children = []
        for dock in self.flatDockList:
            children.append(dock.saveLayout())
        layout["children"] = children

        return layout

    def loadLayout(self, layout):

        for k, child in enumerate(layout["children"]):
            module_str = child["module"]
            class_str = child["class"]

            # Bootstrap part II: Make the child containers
            mod = __import__(module_str, fromlist=[class_str])
            klass = getattr(mod, class_str)

            child_obj = klass()
            self.addItem(k, child_obj)

            child_obj.loadLayout(child)