Beispiel #1
0
    def __init__(self, session, ui_area):
        from PyQt5.QtWidgets import QBoxLayout
        self.session = session
        from chimerax.core.commands import run
        from .options import CategorizedSettingsPanel
        self.options_widget = CategorizedSettingsPanel(help_cb=lambda *, category=None, ses=session, run=run:
            run(ses, "help help:user/preferences.html"
            + ("" if category is None else "#" + category.replace(' ', '').lower())))
        self.options = {}

        for setting, setting_info in self.settings_info.items():
            opt_name, category, opt_class, updater, converter, balloon, set_setting = setting_info
            if isinstance(opt_class, tuple):
                opt_class, kw = opt_class
                if 'session' in kw:
                    kw['session'] = self.session
            else:
                kw = {}
            opt = opt_class(opt_name, getattr(core_settings, setting), self._opt_cb,
                attr_name=setting, settings=core_settings, balloon=balloon, auto_set_attr=set_setting, **kw)
            self.options_widget.add_option(category, opt)
            self.options[setting] = opt

        core_settings.triggers.add_handler('setting changed', self._core_setting_changed)
        layout = QBoxLayout(QBoxLayout.TopToBottom)
        layout.setSpacing(5)
        layout.addWidget(self.options_widget, 1)
        layout.setContentsMargins(0, 0, 0, 0)

        ui_area.setLayout(layout)
Beispiel #2
0
    def __init__(self, viewport):
        super().__init__()
        self.viewport = viewport
        self.moduleName = "QViewportHeader"

        self.setContentsMargins(0, 0, 0, 0)
        boxLayout = QBoxLayout(QBoxLayout.LeftToRight)
        boxLayout.setContentsMargins(0, 0, 0, 0)
        boxLayout.setSpacing(0)
        self.setLayout(boxLayout)

        titleBtn = QToolButton()
        titleBtn.setAutoRaise(True)
        titleBtn.setToolButtonStyle(Qt.ToolButtonTextOnly)
        titleBtn.setPopupMode(QToolButton.InstantPopup)
        self.titleBtn = titleBtn

        pivotSnapping = QToolButton()
        pivotSnapping.setToolTip("Pivot Snapping")
        pivotSnapping.setAutoRaise(True)
        pivotSnapping.setCheckable(True)
        self.pivotSnapping = pivotSnapping

        boxLayout.addWidget(titleBtn, 1)

        boxLayout.addStretch(1)
Beispiel #3
0
 def createLayout(self, orientation, widget):
     layout = QBoxLayout(QBoxLayout.LeftToRight, widget)
     if (orientation == Qt.Vertical):
         layout.setDirection(QBoxLayout.TopToBottom)
     layout.setSpacing(20)
     layout.setContentsMargins(0, 0, 0, 0)
     return layout
Beispiel #4
0
    def __init__(self, parent=None):
        super(FlowSolvingPopup, self).__init__(parent)

        layout = QBoxLayout(QBoxLayout.TopToBottom)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)

        self._solverWidget = FlowSolverWidget()
        self._solverWidget.finished.connect(self._solverFinished)
        layout.addWidget(self._solverWidget)

        status = QStatusBar()
        status.setSizeGripEnabled(False)

        self._againButton = QPushButton("next")
        self._againButton.setVisible(False)
        self._againButton.clicked.connect(self._againClicked)
        status.addPermanentWidget(self._againButton)

        self._abortButton = QPushButton("close")
        self._abortButton.clicked.connect(self._abortClicked)
        status.addPermanentWidget(self._abortButton)

        self._messageLabel = QLabel("ready")
        status.addWidget(self._messageLabel)
        layout.addWidget(status)

        layout.setSizeConstraint(QLayout.SetFixedSize)
        self.setLayout(layout)

        self._timer = QTimer()
        self._timer.timeout.connect(self._timerTick)
Beispiel #5
0
class MainWidget(QWidget):
    def __init__(self, urls, toggle_sequence):
        super(MainWidget, self).__init__()

        self._connection = connection.Connection(self.set_captive_portal_url)
        self._captive_portal_url = ''
        self._urls = cycle(urls)
        self._current_url = next(self._urls)
        self._browser_widget = browser_widget.BrowserWidget(self._current_url)
        self._is_captive_portal_visible = False
        self._captive_portal_message = captive_portal_message.CaptivePortalMessage(
            self._toggle_captive_portal)

        self._layout = QBoxLayout(QBoxLayout.BottomToTop)
        self._layout.setContentsMargins(0, 0, 0, 0)
        self._layout.setSpacing(0)
        self._layout.addWidget(self._browser_widget)

        QShortcut(toggle_sequence, self).activated.connect(self._load_next_url)

        self.setLayout(self._layout)
        self.show()
        self._connection.start_daemon()

    def set_captive_portal_url(self, url):
        self._captive_portal_url = url
        if url == '' and not self._is_captive_portal_visible:
            self._captive_portal_message.setParent(None)
        else:
            self._update_captive_portal_message()
            self._layout.addWidget(self._captive_portal_message)

    # Private

    def _load_next_url(self):
        if self._is_captive_portal_visible:
            self._browser_widget.load(self._current_url)
            self._is_captive_portal_visible = False
            self._update_captive_portal_message()
        else:
            self._current_url = next(self._urls)
            self._browser_widget.load(self._current_url)

    def _toggle_captive_portal(self):
        if self._is_captive_portal_visible:
            if not self._connection.is_captive():
                self._captive_portal_message.setParent(None)
            self._browser_widget.load(self._current_url)
        else:
            self._browser_widget.load(QUrl(self._captive_portal_url))
        self._is_captive_portal_visible = not self._is_captive_portal_visible
        self._update_captive_portal_message()

    def _update_captive_portal_message(self):
        if self._is_captive_portal_visible:
            self._captive_portal_message.setCloseMessage(
                self._connection.is_captive())
        else:
            self._captive_portal_message.setOpenMessage()
Beispiel #6
0
    def __init__(self, function_list, plot_canvas, parent=None):
        super().__init__(parent)

        # Prevent closing
        self.setFeatures(QDockWidget.DockWidgetMovable
                         | QDockWidget.DockWidgetFloatable)

        # Initialize layout
        contents = QWidget()
        layout = QBoxLayout(QBoxLayout.LeftToRight, contents)
        layout.setContentsMargins(10, 0, 10, 20)
        self.setWidget(contents)

        # Add function selection dropdown to layout
        label_combobox = QLabel()
        label_combobox.setText("<b>Function:</b>")
        layout.addWidget(label_combobox)
        layout.setAlignment(label_combobox, Qt.AlignCenter)
        combobox_function = QComboBox()

        # Add functions to dropdown, create map so we can associate values back
        # with original function objects
        self._function_map = {}
        for function in function_list:
            item_text = f"{function.name}: {function.description}"
            combobox_function.addItem(item_text)
            self._function_map[item_text] = function
        layout.addWidget(combobox_function)

        # Add "A" parameter slider to layout
        slider_a = FancySlider("A", -10.0, 10.0, 20)
        layout.addWidget(slider_a)

        # Add "B" parameter slider to layout
        slider_b = FancySlider("B", -10.0, 10.0, 20)
        layout.addWidget(slider_b)

        # Event handlers: update the plot whenever a relevant change is made
        combobox_function.currentTextChanged.connect(self.updatePlot)
        slider_a.valueChanged.connect(self.updatePlot)
        slider_b.valueChanged.connect(self.updatePlot)

        # Event handler: rotate our dock based on where the user puts it
        self.dockLocationChanged.connect(self.updateDockOrientation)

        # Save some elements for later access
        self._layout = layout
        self._combobox_function = combobox_function
        self._slider_a = slider_a
        self._slider_b = slider_b
        self._plot_canvas = plot_canvas

        # Render initial state
        self.updatePlot()
Beispiel #7
0
 def __init__(self, actions=None, parent=None,
              direction=QBoxLayout.LeftToRight):
     QWidget.__init__(self, parent)
     self.actions = []
     self.buttons = []
     layout = QBoxLayout(direction)
     layout.setContentsMargins(0, 0, 0, 0)
     self.setContentsMargins(0, 0, 0, 0)
     self.setLayout(layout)
     if actions is not None:
         for action in actions:
             self.addAction(action)
     self.setLayout(layout)
    def __init__(self, parent: QWidget):

        super().__init__(parent)

        # roi selection
        self.roi_button = RoiSelectionButton(self)

        # layout
        layout = QBoxLayout(QBoxLayout.LeftToRight)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.roi_button)
        layout.setAlignment(self.roi_button, Qt.AlignLeft)
        self.setLayout(layout)
        self.adjustSize()
        self.setStyleSheet("border: 1px solid red")
Beispiel #9
0
 def styleHelper(self):
     layout = QBoxLayout(QBoxLayout.LeftToRight)
     layout.setSpacing(0)
     layout.setContentsMargins(0, 0, 0, 0)
     for item in TOOL_ICONS.items():
         _name, _attr = item
         self.items[_name] = ToolBarIcon(self, item)
         layout.addWidget(self.items[_name], 0, Qt.AlignJustify)
         pass
     self.setLayout(layout)
     #
     self.setFixedSize(*CFG.SIZE_TOPBAR_MAIN())
     self.setVisible(False)
     self.setStyleSheet(CFG.STYLESHEET(self))
     pass
Beispiel #10
0
 def __init__(self,
              actions=None,
              parent=None,
              direction=QBoxLayout.LeftToRight):
     QWidget.__init__(self, parent)
     self.actions = []
     self.buttons = []
     layout = QBoxLayout(direction)
     layout.setContentsMargins(0, 0, 0, 0)
     self.setContentsMargins(0, 0, 0, 0)
     self.setLayout(layout)
     if actions is not None:
         for action in actions:
             self.addAction(action)
     self.setLayout(layout)
Beispiel #11
0
    def __init__(self):
        super().__init__()
        self.setMinimumSize(300, 400)
        self.setMaximumSize(400, 2000)
        layout = QBoxLayout(QBoxLayout.TopToBottom)
        layout.setContentsMargins(0, 0, 0, 0)  # 取消组件间间隙
        self.treeView = FolderTreeView()
        layout.addWidget(self.treeView)
        self.loadFromFile()
        self.setLayout(layout)
        self.treeView.clicked.connect(self.onTreeNodeClicked)
        self.treeView.customContextMenuRequested.connect(self.showContextMenu)

        # 鼠标选中的item
        self.clickedItem = None
Beispiel #12
0
    def __init__(self, qtpy):
        super().__init__()
        self.qtpy = qtpy

        self.setObjectName("devrant_secondary_panel")
        self.setFixedHeight(60)

        self.label = QLabel()
        self.label.setObjectName("devrant_title_label")
        self.label.setText(self.qtpy.language.get("service_name"))

        layout = QBoxLayout(QBoxLayout.LeftToRight)
        layout.addWidget(self.label)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)
Beispiel #13
0
    def __init__(self, qtpy):
        super().__init__(qtpy)
        self.setWindowTitle(qtpy.language.get("app_name"))

        self.header = Header(qtpy)

        self.main_widget = QWidget()
        layout = QBoxLayout(QBoxLayout.TopToBottom)
        layout.setAlignment(Qt.AlignTop)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.header)
        self.main_widget.setLayout(layout)

        self.setCentralWidget(self.main_widget)

        apply_theme(self.qtpy.client, self.main_widget)
Beispiel #14
0
class SceneTree(QDockWidget):
    def __init__(self, parent=None):
        super(SceneTree, self).__init__(parent)

        self.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        self.setFeatures(QDockWidget.NoDockWidgetFeatures)

        self.centralwidget = QWidget(self)
        self.setWidget(self.centralwidget)

        self.layout = QBoxLayout(QBoxLayout.TopToBottom, self.centralwidget)

        self.tree = QTreeWidget()
        self.layout.addWidget(self.tree)
        self.layout.setContentsMargins(0, 0, 0, 0)
        # TODO : Delete btn_add and use context menu, which appears when right mouse clicked
        self.btn_add = QPushButton('Add ..')
        self.layout.addWidget(self.btn_add)
    def __init__(self, image: QImage):
        """
        @param image: image to show
        """

        # GUI constructor
        super().__init__()

        # graphics scene
        self.scene = ImageScene(image)

        # ROIs
        self.scene.add_roi(RectangleRoi(50, 10, 50, 40))
        self.scene.add_roi(RectangleRoi(100, 50, 100, 20))
        self.scene.add_roi(EllipseRoi(75, 20, 60, 20))
        self.scene.rois[-1].set_properties(color_rgb=[255, 0, 0],
                                           line_width=6.0)
        self.scene.add_roi(EllipseRoi(120, 70, 8, 8))
        self.scene.add_roi(
            PathRoi([10, 60], [10, 50], is_closed=False, is_anchored=True))
        self.scene.rois[-1].set_properties(color_rgb=[30, 255, 0],
                                           line_width=6.0)
        self.scene.add_roi(
            PathRoi([60, 65, 75], [60, 76, 50],
                    is_closed=True,
                    is_anchored=True))
        self.scene.add_roi(PointRoi(120, 50, size=6))

        # graphics view
        self.viewer = QGraphicsView(self.scene)
        self.viewer.setSceneRect(0, 0, self.scene.width(), self.scene.height())
        self.viewer.setInteractive(True)
        self.viewer.show()
        self.scale = 1.0

        # menu
        self.menu = ImageMenu(self)

        # layout
        layout = QBoxLayout(QBoxLayout.TopToBottom)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.menu)
        layout.addWidget(self.viewer)
        self.setLayout(layout)
Beispiel #16
0
def install_layout_for_widget(widget, orientation=None, margins=None, spacing=None):
    """
    Installs a layout to widget, if it does not have it already.
    :param widget: target widget
    :param orientation: Qt.Vertical (default) / Qt.Horizontal
    :param margins: layout margins = (11, 11, 11, 11) from Qt docs, style dependent
    :param spacing: spacing between items in layout
    :return: None
    """
    if widget.layout() is not None:
        logger.debug('Widget {0} already has a layout, skipping'.format(widget.windowTitle()))
        return  # already has a layout
    direction = QBoxLayout.TopToBottom
    if orientation == Qt.Horizontal:
        direction = QBoxLayout.LeftToRight
    l = QBoxLayout(direction)
    if margins is not None:
        l.setContentsMargins(margins[0], margins[1], margins[2], margins[3])
    if spacing is not None:
        l.setSpacing(spacing)
    widget.setLayout(l)
Beispiel #17
0
class E5SideBar(QWidget):
    """
    Class implementing a sidebar with a widget area, that is hidden or shown,
    if the current tab is clicked again.
    """
    Version = 1

    North = 0
    East = 1
    South = 2
    West = 3

    def __init__(self, orientation=None, delay=200, parent=None):
        """
        Constructor
        
        @param orientation orientation of the sidebar widget (North, East,
            South, West)
        @param delay value for the expand/shrink delay in milliseconds
            (integer)
        @param parent parent widget (QWidget)
        """
        super(E5SideBar, self).__init__(parent)

        self.__tabBar = QTabBar()
        self.__tabBar.setDrawBase(True)
        self.__tabBar.setShape(QTabBar.RoundedNorth)
        self.__tabBar.setUsesScrollButtons(True)
        self.__tabBar.setDrawBase(False)
        self.__stackedWidget = QStackedWidget(self)
        self.__stackedWidget.setContentsMargins(0, 0, 0, 0)
        self.__autoHideButton = QToolButton()
        self.__autoHideButton.setCheckable(True)
        self.__autoHideButton.setIcon(
            UI.PixmapCache.getIcon("autoHideOff.png"))
        self.__autoHideButton.setChecked(True)
        self.__autoHideButton.setToolTip(
            self.tr("Deselect to activate automatic collapsing"))
        self.barLayout = QBoxLayout(QBoxLayout.LeftToRight)
        self.barLayout.setContentsMargins(0, 0, 0, 0)
        self.layout = QBoxLayout(QBoxLayout.TopToBottom)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(0)
        self.barLayout.addWidget(self.__autoHideButton)
        self.barLayout.addWidget(self.__tabBar)
        self.layout.addLayout(self.barLayout)
        self.layout.addWidget(self.__stackedWidget)
        self.setLayout(self.layout)

        # initialize the delay timer
        self.__actionMethod = None
        self.__delayTimer = QTimer(self)
        self.__delayTimer.setSingleShot(True)
        self.__delayTimer.setInterval(delay)
        self.__delayTimer.timeout.connect(self.__delayedAction)

        self.__minimized = False
        self.__minSize = 0
        self.__maxSize = 0
        self.__bigSize = QSize()

        self.splitter = None
        self.splitterSizes = []

        self.__hasFocus = False
        # flag storing if this widget or any child has the focus
        self.__autoHide = False

        self.__tabBar.installEventFilter(self)

        self.__orientation = E5SideBar.North
        if orientation is None:
            orientation = E5SideBar.North
        self.setOrientation(orientation)

        self.__tabBar.currentChanged[int].connect(
            self.__stackedWidget.setCurrentIndex)
        e5App().focusChanged.connect(self.__appFocusChanged)
        self.__autoHideButton.toggled[bool].connect(self.__autoHideToggled)

    def setSplitter(self, splitter):
        """
        Public method to set the splitter managing the sidebar.
        
        @param splitter reference to the splitter (QSplitter)
        """
        self.splitter = splitter
        self.splitter.splitterMoved.connect(self.__splitterMoved)
        self.splitter.setChildrenCollapsible(False)
        index = self.splitter.indexOf(self)
        self.splitter.setCollapsible(index, False)

    def __splitterMoved(self, pos, index):
        """
        Private slot to react on splitter moves.
        
        @param pos new position of the splitter handle (integer)
        @param index index of the splitter handle (integer)
        """
        if self.splitter:
            self.splitterSizes = self.splitter.sizes()

    def __delayedAction(self):
        """
        Private slot to handle the firing of the delay timer.
        """
        if self.__actionMethod is not None:
            self.__actionMethod()

    def setDelay(self, delay):
        """
        Public method to set the delay value for the expand/shrink delay in
        milliseconds.
        
        @param delay value for the expand/shrink delay in milliseconds
            (integer)
        """
        self.__delayTimer.setInterval(delay)

    def delay(self):
        """
        Public method to get the delay value for the expand/shrink delay in
        milliseconds.
        
        @return value for the expand/shrink delay in milliseconds (integer)
        """
        return self.__delayTimer.interval()

    def __cancelDelayTimer(self):
        """
        Private method to cancel the current delay timer.
        """
        self.__delayTimer.stop()
        self.__actionMethod = None

    def shrink(self):
        """
        Public method to record a shrink request.
        """
        self.__delayTimer.stop()
        self.__actionMethod = self.__shrinkIt
        self.__delayTimer.start()

    def __shrinkIt(self):
        """
        Private method to shrink the sidebar.
        """
        self.__minimized = True
        self.__bigSize = self.size()
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            self.__minSize = self.minimumSizeHint().height()
            self.__maxSize = self.maximumHeight()
        else:
            self.__minSize = self.minimumSizeHint().width()
            self.__maxSize = self.maximumWidth()
        if self.splitter:
            self.splitterSizes = self.splitter.sizes()

        self.__stackedWidget.hide()

        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            self.setFixedHeight(self.__tabBar.minimumSizeHint().height())
        else:
            self.setFixedWidth(self.__tabBar.minimumSizeHint().width())

        self.__actionMethod = None

    def expand(self):
        """
        Public method to record a expand request.
        """
        self.__delayTimer.stop()
        self.__actionMethod = self.__expandIt
        self.__delayTimer.start()

    def __expandIt(self):
        """
        Private method to expand the sidebar.
        """
        self.__minimized = False
        self.__stackedWidget.show()
        self.resize(self.__bigSize)
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            minSize = max(self.__minSize, self.minimumSizeHint().height())
            self.setMinimumHeight(minSize)
            self.setMaximumHeight(self.__maxSize)
        else:
            minSize = max(self.__minSize, self.minimumSizeHint().width())
            self.setMinimumWidth(minSize)
            self.setMaximumWidth(self.__maxSize)
        if self.splitter:
            self.splitter.setSizes(self.splitterSizes)

        self.__actionMethod = None

    def isMinimized(self):
        """
        Public method to check the minimized state.
        
        @return flag indicating the minimized state (boolean)
        """
        return self.__minimized

    def isAutoHiding(self):
        """
        Public method to check, if the auto hide function is active.
        
        @return flag indicating the state of auto hiding (boolean)
        """
        return self.__autoHide

    def eventFilter(self, obj, evt):
        """
        Public method to handle some events for the tabbar.
        
        @param obj reference to the object (QObject)
        @param evt reference to the event object (QEvent)
        @return flag indicating, if the event was handled (boolean)
        """
        if obj == self.__tabBar:
            if evt.type() == QEvent.MouseButtonPress:
                pos = evt.pos()
                for i in range(self.__tabBar.count()):
                    if self.__tabBar.tabRect(i).contains(pos):
                        break

                if i == self.__tabBar.currentIndex():
                    if self.isMinimized():
                        self.expand()
                    else:
                        self.shrink()
                    return True
                elif self.isMinimized():
                    self.expand()
            elif evt.type() == QEvent.Wheel:
                if qVersion() >= "5.0.0":
                    delta = evt.angleDelta().y()
                else:
                    delta = evt.delta()
                if delta > 0:
                    self.prevTab()
                else:
                    self.nextTab()
                return True

        return QWidget.eventFilter(self, obj, evt)

    def addTab(self, widget, iconOrLabel, label=None):
        """
        Public method to add a tab to the sidebar.
        
        @param widget reference to the widget to add (QWidget)
        @param iconOrLabel reference to the icon or the label text of the tab
            (QIcon, string)
        @param label the labeltext of the tab (string) (only to be
            used, if the second parameter is a QIcon)
        """
        if label:
            index = self.__tabBar.addTab(iconOrLabel, label)
            self.__tabBar.setTabToolTip(index, label)
        else:
            index = self.__tabBar.addTab(iconOrLabel)
            self.__tabBar.setTabToolTip(index, iconOrLabel)
        self.__stackedWidget.addWidget(widget)
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            self.__minSize = self.minimumSizeHint().height()
        else:
            self.__minSize = self.minimumSizeHint().width()

    def insertTab(self, index, widget, iconOrLabel, label=None):
        """
        Public method to insert a tab into the sidebar.
        
        @param index the index to insert the tab at (integer)
        @param widget reference to the widget to insert (QWidget)
        @param iconOrLabel reference to the icon or the labeltext of the tab
            (QIcon, string)
        @param label the labeltext of the tab (string) (only to be
            used, if the second parameter is a QIcon)
        """
        if label:
            index = self.__tabBar.insertTab(index, iconOrLabel, label)
            self.__tabBar.setTabToolTip(index, label)
        else:
            index = self.__tabBar.insertTab(index, iconOrLabel)
            self.__tabBar.setTabToolTip(index, iconOrLabel)
        self.__stackedWidget.insertWidget(index, widget)
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            self.__minSize = self.minimumSizeHint().height()
        else:
            self.__minSize = self.minimumSizeHint().width()

    def removeTab(self, index):
        """
        Public method to remove a tab.
        
        @param index the index of the tab to remove (integer)
        """
        self.__stackedWidget.removeWidget(self.__stackedWidget.widget(index))
        self.__tabBar.removeTab(index)
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            self.__minSize = self.minimumSizeHint().height()
        else:
            self.__minSize = self.minimumSizeHint().width()

    def clear(self):
        """
        Public method to remove all tabs.
        """
        while self.count() > 0:
            self.removeTab(0)

    def prevTab(self):
        """
        Public slot used to show the previous tab.
        """
        ind = self.currentIndex() - 1
        if ind == -1:
            ind = self.count() - 1

        self.setCurrentIndex(ind)
        self.currentWidget().setFocus()

    def nextTab(self):
        """
        Public slot used to show the next tab.
        """
        ind = self.currentIndex() + 1
        if ind == self.count():
            ind = 0

        self.setCurrentIndex(ind)
        self.currentWidget().setFocus()

    def count(self):
        """
        Public method to get the number of tabs.
        
        @return number of tabs in the sidebar (integer)
        """
        return self.__tabBar.count()

    def currentIndex(self):
        """
        Public method to get the index of the current tab.
        
        @return index of the current tab (integer)
        """
        return self.__stackedWidget.currentIndex()

    def setCurrentIndex(self, index):
        """
        Public slot to set the current index.
        
        @param index the index to set as the current index (integer)
        """
        self.__tabBar.setCurrentIndex(index)
        self.__stackedWidget.setCurrentIndex(index)
        if self.isMinimized():
            self.expand()

    def currentWidget(self):
        """
        Public method to get a reference to the current widget.
        
        @return reference to the current widget (QWidget)
        """
        return self.__stackedWidget.currentWidget()

    def setCurrentWidget(self, widget):
        """
        Public slot to set the current widget.
        
        @param widget reference to the widget to become the current widget
            (QWidget)
        """
        self.__stackedWidget.setCurrentWidget(widget)
        self.__tabBar.setCurrentIndex(self.__stackedWidget.currentIndex())
        if self.isMinimized():
            self.expand()

    def indexOf(self, widget):
        """
        Public method to get the index of the given widget.
        
        @param widget reference to the widget to get the index of (QWidget)
        @return index of the given widget (integer)
        """
        return self.__stackedWidget.indexOf(widget)

    def isTabEnabled(self, index):
        """
        Public method to check, if a tab is enabled.
        
        @param index index of the tab to check (integer)
        @return flag indicating the enabled state (boolean)
        """
        return self.__tabBar.isTabEnabled(index)

    def setTabEnabled(self, index, enabled):
        """
        Public method to set the enabled state of a tab.
        
        @param index index of the tab to set (integer)
        @param enabled enabled state to set (boolean)
        """
        self.__tabBar.setTabEnabled(index, enabled)

    def orientation(self):
        """
        Public method to get the orientation of the sidebar.
        
        @return orientation of the sidebar (North, East, South, West)
        """
        return self.__orientation

    def setOrientation(self, orient):
        """
        Public method to set the orientation of the sidebar.

        @param orient orientation of the sidebar (North, East, South, West)
        """
        if orient == E5SideBar.North:
            self.__tabBar.setShape(QTabBar.RoundedNorth)
            self.__tabBar.setSizePolicy(QSizePolicy.Expanding,
                                        QSizePolicy.Preferred)
            self.barLayout.setDirection(QBoxLayout.LeftToRight)
            self.layout.setDirection(QBoxLayout.TopToBottom)
            self.layout.setAlignment(self.barLayout, Qt.AlignLeft)
        elif orient == E5SideBar.East:
            self.__tabBar.setShape(QTabBar.RoundedEast)
            self.__tabBar.setSizePolicy(QSizePolicy.Preferred,
                                        QSizePolicy.Expanding)
            self.barLayout.setDirection(QBoxLayout.TopToBottom)
            self.layout.setDirection(QBoxLayout.RightToLeft)
            self.layout.setAlignment(self.barLayout, Qt.AlignTop)
        elif orient == E5SideBar.South:
            self.__tabBar.setShape(QTabBar.RoundedSouth)
            self.__tabBar.setSizePolicy(QSizePolicy.Expanding,
                                        QSizePolicy.Preferred)
            self.barLayout.setDirection(QBoxLayout.LeftToRight)
            self.layout.setDirection(QBoxLayout.BottomToTop)
            self.layout.setAlignment(self.barLayout, Qt.AlignLeft)
        elif orient == E5SideBar.West:
            self.__tabBar.setShape(QTabBar.RoundedWest)
            self.__tabBar.setSizePolicy(QSizePolicy.Preferred,
                                        QSizePolicy.Expanding)
            self.barLayout.setDirection(QBoxLayout.TopToBottom)
            self.layout.setDirection(QBoxLayout.LeftToRight)
            self.layout.setAlignment(self.barLayout, Qt.AlignTop)
        self.__orientation = orient

    def tabIcon(self, index):
        """
        Public method to get the icon of a tab.
        
        @param index index of the tab (integer)
        @return icon of the tab (QIcon)
        """
        return self.__tabBar.tabIcon(index)

    def setTabIcon(self, index, icon):
        """
        Public method to set the icon of a tab.
        
        @param index index of the tab (integer)
        @param icon icon to be set (QIcon)
        """
        self.__tabBar.setTabIcon(index, icon)

    def tabText(self, index):
        """
        Public method to get the text of a tab.
        
        @param index index of the tab (integer)
        @return text of the tab (string)
        """
        return self.__tabBar.tabText(index)

    def setTabText(self, index, text):
        """
        Public method to set the text of a tab.
        
        @param index index of the tab (integer)
        @param text text to set (string)
        """
        self.__tabBar.setTabText(index, text)

    def tabToolTip(self, index):
        """
        Public method to get the tooltip text of a tab.
        
        @param index index of the tab (integer)
        @return tooltip text of the tab (string)
        """
        return self.__tabBar.tabToolTip(index)

    def setTabToolTip(self, index, tip):
        """
        Public method to set the tooltip text of a tab.
        
        @param index index of the tab (integer)
        @param tip tooltip text to set (string)
        """
        self.__tabBar.setTabToolTip(index, tip)

    def tabWhatsThis(self, index):
        """
        Public method to get the WhatsThis text of a tab.
        
        @param index index of the tab (integer)
        @return WhatsThis text of the tab (string)
        """
        return self.__tabBar.tabWhatsThis(index)

    def setTabWhatsThis(self, index, text):
        """
        Public method to set the WhatsThis text of a tab.
        
        @param index index of the tab (integer)
        @param text WhatsThis text to set (string)
        """
        self.__tabBar.setTabWhatsThis(index, text)

    def widget(self, index):
        """
        Public method to get a reference to the widget associated with a tab.
        
        @param index index of the tab (integer)
        @return reference to the widget (QWidget)
        """
        return self.__stackedWidget.widget(index)

    def saveState(self):
        """
        Public method to save the state of the sidebar.
        
        @return saved state as a byte array (QByteArray)
        """
        if len(self.splitterSizes) == 0:
            if self.splitter:
                self.splitterSizes = self.splitter.sizes()
            self.__bigSize = self.size()
            if self.__orientation in [E5SideBar.North, E5SideBar.South]:
                self.__minSize = self.minimumSizeHint().height()
                self.__maxSize = self.maximumHeight()
            else:
                self.__minSize = self.minimumSizeHint().width()
                self.__maxSize = self.maximumWidth()

        data = QByteArray()
        stream = QDataStream(data, QIODevice.WriteOnly)
        stream.setVersion(QDataStream.Qt_4_6)

        stream.writeUInt16(self.Version)
        stream.writeBool(self.__minimized)
        stream << self.__bigSize
        stream.writeUInt16(self.__minSize)
        stream.writeUInt16(self.__maxSize)
        stream.writeUInt16(len(self.splitterSizes))
        for size in self.splitterSizes:
            stream.writeUInt16(size)
        stream.writeBool(self.__autoHide)

        return data

    def restoreState(self, state):
        """
        Public method to restore the state of the sidebar.
        
        @param state byte array containing the saved state (QByteArray)
        @return flag indicating success (boolean)
        """
        if state.isEmpty():
            return False

        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            minSize = self.layout.minimumSize().height()
            maxSize = self.maximumHeight()
        else:
            minSize = self.layout.minimumSize().width()
            maxSize = self.maximumWidth()

        data = QByteArray(state)
        stream = QDataStream(data, QIODevice.ReadOnly)
        stream.setVersion(QDataStream.Qt_4_6)
        stream.readUInt16()  # version
        minimized = stream.readBool()

        if minimized and not self.__minimized:
            self.shrink()

        stream >> self.__bigSize
        self.__minSize = max(stream.readUInt16(), minSize)
        self.__maxSize = max(stream.readUInt16(), maxSize)
        count = stream.readUInt16()
        self.splitterSizes = []
        for i in range(count):
            self.splitterSizes.append(stream.readUInt16())

        self.__autoHide = stream.readBool()
        self.__autoHideButton.setChecked(not self.__autoHide)

        if not minimized:
            self.expand()

        return True

    #######################################################################
    ## methods below implement the autohide functionality
    #######################################################################

    def __autoHideToggled(self, checked):
        """
        Private slot to handle the toggling of the autohide button.
        
        @param checked flag indicating the checked state of the button
            (boolean)
        """
        self.__autoHide = not checked
        if self.__autoHide:
            self.__autoHideButton.setIcon(
                UI.PixmapCache.getIcon("autoHideOn.png"))
        else:
            self.__autoHideButton.setIcon(
                UI.PixmapCache.getIcon("autoHideOff.png"))

    def __appFocusChanged(self, old, now):
        """
        Private slot to handle a change of the focus.
        
        @param old reference to the widget, that lost focus (QWidget or None)
        @param now reference to the widget having the focus (QWidget or None)
        """
        self.__hasFocus = self.isAncestorOf(now)
        if self.__autoHide and not self.__hasFocus and not self.isMinimized():
            self.shrink()
        elif self.__autoHide and self.__hasFocus and self.isMinimized():
            self.expand()

    def enterEvent(self, event):
        """
        Protected method to handle the mouse entering this widget.
        
        @param event reference to the event (QEvent)
        """
        if self.__autoHide and self.isMinimized():
            self.expand()
        else:
            self.__cancelDelayTimer()

    def leaveEvent(self, event):
        """
        Protected method to handle the mouse leaving this widget.
        
        @param event reference to the event (QEvent)
        """
        if self.__autoHide and not self.__hasFocus and not self.isMinimized():
            self.shrink()
        else:
            self.__cancelDelayTimer()

    def shutdown(self):
        """
        Public method to shut down the object.
        
        This method does some preparations so the object can be deleted
        properly. It disconnects from the focusChanged signal in order to
        avoid trouble later on.
        """
        e5App().focusChanged.disconnect(self.__appFocusChanged)
Beispiel #18
0
class CToolBarAreaItem(QWidget):
    signalDragStart = pyqtSignal(QWidget)
    signalDragEnd = pyqtSignal(QWidget)

    def __init__(self, area, orientation):
        super().__init__()
        self.area = area
        self.orientation = orientation
        self.content = None
        self.layout_ = QBoxLayout(QBoxLayout.LeftToRight if (
            orientation == Qt.Horizontal) else QBoxLayout.TopToBottom)
        self.layout_.setContentsMargins(0, 0, 0, 0)
        self.layout_.setSpacing(0)

    def setArea(self, area):
        self.area = area

    def setLocked(self, isLocked):
        self.dragHandle.setVisiable(not isLocked)

    def setOrientation(self, orientation):
        self.orientation = orientation
        self.layout_.setDirection(QBoxLayout.LeftToRight if (
            orientation == Qt.Horizontal) else QBoxLayout.TopToBottom)
        self.dragHandle.setOrientation(orientation)

    def getType(self):
        pass

    def getArea(self):
        return self.area

    def getOrientation(self):
        return self.orientation

    def getMinimumSize(self):
        return self.minimumSize()

    def getMimeType(self):
        return "CToolBarAreaItem"

    def onDragStart(self):
        self.signalDragStart.emit(self)

    def onDragEnd(self):
        self.signalDragEnd.emit(self)

    def setContent(self, newContent):
        if self.content == None:
            self.content = newContent
            self.layout_.addWidget(self.content)

        self.layout_.replaceWidget(self.content, newContent)
        self.content.setVisiable(False)
        newContent.setVisiable(True)

        self.content.deleteLater()
        self.content = newContent

    def paintEvent(self, event):
        styleOption = QStyleOption()
        styleOption.initFrom(self)
        painter = QPainter(self)
        self.style().drawPrimitive(QStyle.PE_Widget, styleOption, painter,
                                   self)
    def load_settings_widgets_from_pipeline_groupbox(self, position):
        """
        Extracts all widgets from a single algorithm and returns a QBoxLayout
        Args:
            alg: the alg instance we extract from

        Returns: a QBoxLayout containing all widgets for this particular alg.

        """

        alg = self.pipeline.executed_cats[position].active_algorithm

        print("alg " + str(alg))
        print("cat " + str(self.pipeline.executed_cats[position]))

        empty_flag = True

        groupOfSliders = QGroupBox()
        sp = QSizePolicy()
        sp.setVerticalPolicy(QSizePolicy.Preferred)
        # groupOfSliders.setSizePolicy(sp)
        groupOfSliderssLayout = QBoxLayout(QBoxLayout.TopToBottom)
        groupOfSliderssLayout.setContentsMargins(0, -0, -0, 0)
        groupOfSliderssLayout.setAlignment(Qt.AlignTop)
        groupOfSliderssLayout.setSpacing(0)

        print("Build Slider @ "+ str(position))

        # create integer sliders
        for slider in alg.integer_sliders:
            empty_flag = False
            print("slider.value " + str(slider.value))
            print("slider " + str(slider))
            #print(alg.get_name() + ": add slider (int).")
            groupOfSliderssLayout.addWidget(
                SliderWidget(slider.name, slider.lower, slider.upper, slider.step_size, slider.value,
                             slider.set_value, False))

        # create float sliders
        for slider in alg.float_sliders:
            empty_flag = False
            #print(alg.get_name() + ": add slider (float).")
            groupOfSliderssLayout.addWidget(
                SliderWidget(slider.name, slider.lower, slider.upper, slider.step_size, slider.value,
                             slider.set_value, True), 0, Qt.AlignTop)

        # create checkboxes
        for checkbox in alg.checkboxes:
            empty_flag = False
            #print(alg.get_name() + ": add checkbox.")
            groupOfSliderssLayout.addWidget(CheckBoxWidget(checkbox.name, checkbox.value, checkbox.set_value), 0,
                                            Qt.AlignTop)

        # create dropdowns
        for combobox in alg.drop_downs:
            empty_flag = False
            #print(alg.get_name() + ": add combobox.")
            groupOfSliderssLayout.addWidget(
                ComboBoxWidget(combobox.name, combobox.options, combobox.set_value, combobox.value), 0, Qt.AlignTop)

        if empty_flag:
            label = QLabel()
            label.setText("This algorithm has no Settings.")
            groupOfSliderssLayout.addWidget(label, 0, Qt.AlignHCenter)

        groupOfSliders.setLayout(groupOfSliderssLayout)

        return groupOfSliders
    def __init__(self, parent):
        super(NewsWindow, self).__init__(parent)
        self.parent = parent
        # top table - news list and filters
        self.table = QTableWidget(0, 5)
        horizLabels = ["", "", "", "", ""]
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table.setSelectionMode(QAbstractItemView.SingleSelection)
        self.table.itemSelectionChanged.connect(self.doDisplayNewsHeadline)
        self.table.setHorizontalHeaderLabels(horizLabels)
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.table.setWordWrap(True)
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        topLayout = QGridLayout()
        topLayout.addWidget(self.table, 0, 1)
        filterLayout = QBoxLayout(QBoxLayout.TopToBottom)
        self.filters = [
            QPushButton(parent.graphics.icon[23 + i], "") for i in range(5)
        ]
        filterGroup = QButtonGroup()
        for i, j in zip(self.filters, range(5)):
            i.setFixedSize(120, 32)
            i.setAutoExclusive(True)
            i.setCheckable(True)
            i.released.connect(partial(self.doRefreshNews, j))
            filterGroup.addButton(i)
            filterLayout.addWidget(i)
            filterLayout.addSpacing(-5)
        filterLayout.addSpacing(30)
        filterLayout.setAlignment(Qt.AlignVCenter)
        self.ctryList = QComboBox()
        self.ctryList.setMaxVisibleItems(10)
        self.ctryList.addItems([
            Local.strings[Local.DATA_COUNTRIES + i][Local.CTRY_NAME]
            for i in range(80)
        ])
        self.ctryList.currentIndexChanged.connect(
            partial(self.doRefreshNews, 5))
        self.localNews = QRadioButton()
        self.localNews.released.connect(partial(self.doRefreshNews, 5))
        filterGroup.addButton(self.localNews)
        filterLayout.addWidget(self.localNews)
        filterLayout.addWidget(self.ctryList)
        topLayout.addLayout(filterLayout, 0, 0)
        topLayout.setContentsMargins(-50, 0, 0, 0)
        self.table.setFixedHeight(220)

        # left half - news
        buttons = QBoxLayout(QBoxLayout.LeftToRight)
        leftLayout = QBoxLayout(QBoxLayout.TopToBottom)
        leftLayout.setContentsMargins(-80, 0, 0, 0)
        self.newsHline = QLabel()
        self.newsHline.setWordWrap(True)
        self.newsHline.setFixedHeight(40)
        leftLayout.addSpacing(25)
        leftLayout.addWidget(self.newsHline)
        leftLayout.addSpacing(30)
        self.question = QPushButton()
        self.backDown = QPushButton()
        self.question.released.connect(self.doTough)
        self.backDown.released.connect(self.doLoose)
        for i in (self.question, self.backDown):
            buttons.addWidget(i)
        leftLayout.addLayout(buttons)
        self.reactionLine = QLabel()
        self.reactionLine.setFixedHeight(30)
        self.reactionLine.setWordWrap(True)
        leftLayout.addSpacing(20)
        leftLayout.addWidget(self.reactionLine)
        leftLayout.addSpacing(20)
        leftInfoLayout = [QBoxLayout(QBoxLayout.LeftToRight) for i in range(3)]
        self.leftInfo = [QLabel() for i in range(3)]
        self.leftInfoVal = [QLabel() for i in range(3)]
        for i in range(3):
            leftInfoLayout[i].addWidget(self.leftInfo[i])
            leftInfoLayout[i].addWidget(self.leftInfoVal[i])
            leftLayout.addLayout(leftInfoLayout[i])
            if i < 2: leftLayout.addSpacing(-5)

        # right half - advisory
        rightLayout = QBoxLayout(QBoxLayout.TopToBottom)
        rightLayout.setContentsMargins(0, -50, 0, 0)
        #rightLayout.addWidget(self.advisory)
        headsLayout = QBoxLayout(QBoxLayout.LeftToRight)
        headsColumn = [QBoxLayout(QBoxLayout.TopToBottom) for i in range(2)]
        head = [QBoxLayout(QBoxLayout.LeftToRight) for i in range(4)]
        self.picture = [QLabel() for i in range(4)]
        self.advice = [QLabel() for i in range(4)]
        for i in range(4):
            self.picture[i].setPixmap(parent.graphics.advisor[i])
            self.advice[i].setWordWrap(True)
            self.advice[i].setFixedWidth(100)
            head[i].addWidget(self.picture[i])
            head[i].addWidget(self.advice[i])
            headsColumn[i // 2].addLayout(head[i])
        self.closeUpButton = QPushButton()

        for i in range(2):
            headsLayout.addLayout(headsColumn[i])
        rightLayout.addLayout(headsLayout)

        # save right and left layouts into groups
        self.detailGroup = [QGroupBox() for i in range(3)]
        self.detailGroup[0].setLayout(leftLayout)
        self.detailGroup[1].setLayout(rightLayout)
        self.detailGroup[2].setLayout(topLayout)

        mainLayout = QGridLayout()
        mainLayout.addWidget(self.detailGroup[2], 0, 0, 1, 2)
        for i in range(2):
            mainLayout.addWidget(self.detailGroup[i], 1, i)

        self.setStrings()
        self.setLayout(mainLayout)
        self.setFixedSize(830, 590)
        self.setModal(True)
Beispiel #21
0
class Window(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self._init_widget()

    def _init_widget(self):
        self.setWindowTitle("Kiwoomium")
        self.setGeometry(100, 100, 1440, 960)
        self.setMinimumSize(1024, 768)

        self.toolbar = Toolbar()
        self.statusbar = StatusBar()
        self.webview = WebView()

        self._init_toolbar()
        self._init_webview()
        self._init_devtool()
        self._init_shortcut()
        self._init_layout()

    def _init_layout(self):
        self.main_widget = QWidget()
        self.layout = QBoxLayout(QBoxLayout.LeftToRight)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.splitter = QSplitter()
        self.splitter.setOrientation(Qt.Horizontal)
        self.splitter.addWidget(self.webview)
        self.splitter.addWidget(self.devtool)
        self.splitter.setSizes([65, 35])
        self.layout.addWidget(self.splitter)
        self.main_widget.setLayout(self.layout)

        self.addToolBar(self.toolbar)
        self.setCentralWidget(self.main_widget)
        self.setStatusBar(self.statusbar)
        self.setWindowIcon(QIcon('assets/svg/gold.svg'))

    def _init_webview(self):
        self.webview.setUrl(QUrl("http://localhost:3000"))
        self.webview.loadProgress.connect(
            lambda progress: self.toolbar.changeStopReload(
                bool(0 <= progress >= 100)))
        self.webview.loadProgress.connect(self.statusbar.setProgressValue)

    def _init_devtool(self):
        self.devtool = DevTool(self.webview)

    def _init_toolbar(self):
        self.toolbar.backButtonClicked.connect(self.webview.back)
        self.toolbar.forwardButtonClicked.connect(self.webview.forward)
        self.toolbar.stopReloadButtonClicked.connect(
            lambda v: self.webview.triggerPageAction(v))
        self.toolbar.addressChanged.connect(
            lambda v: self.webview.setUrl(QUrl(v)))

    def _init_shortcut(self):
        self.shortcut = {}
        self.shortcut['F12'] = QShortcut(self)
        self.shortcut['F12'].setContext(Qt.ApplicationShortcut)
        self.shortcut['F12'].setKey(Qt.Key_F12)
        self.shortcut['F12'].activated.connect(self._toggle_devtool)

        self.shortcut['CTRL+R'] = QShortcut(self)
        self.shortcut['CTRL+R'].setContext(Qt.ApplicationShortcut)
        self.shortcut['CTRL+R'].setKey(Qt.CTRL + Qt.Key_R)
        self.shortcut['CTRL+R'].activated.connect(self.webview.reload)

    def _toggle_devtool(self):
        self.devtool.setVisible(not self.devtool.isVisible())
window = QWidget()

btn1 = QPushButton("One")
btn2 = QPushButton("Two")
btn3 = QPushButton("Three")

# Set the layout

box = QBoxLayout(QBoxLayout.Direction(0))  # TODO

box.addWidget(btn1)
box.addWidget(btn2)
box.addWidget(btn3)

box.setContentsMargins(0, 0, 0, 0)  # set the spacing around the layout (in pixels)
box.setSpacing(0)                   # set the spacing between elements (in pixels)

window.setLayout(box)

# Show
window.show()

# The mainloop of the application. The event handling starts from this point.
# The exec_() method has an underscore. It is because the exec is a Python keyword. And thus, exec_() was used instead.
exit_code = app.exec_()

# The sys.exit() method ensures a clean exit.
# The environment will be informed, how the application ended.
sys.exit(exit_code)
Beispiel #23
0
class QCustomWindowFrame(QFrame):
    contentsChanged = pyqtSignal(QWidget)

    def __init__(self):
        super(QCustomWindowFrame, self).__init__(None)
        self.titleBar = None
        self.contents = None
        self.sizeGrip = None
        self.resizeMargin = 4

        self.setMouseTracking(True)

        self.layout = QBoxLayout(QBoxLayout.TopToBottom)
        self.layout.setSpacing(0)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(self.layout)

    def __del__(self):
        pass

    @staticmethod
    def wrapWidget(w):
        windowFrame = QCustomWindowFrame()
        windowFrame.internalSetContents(w)
        return windowFrame

    def ensureTitleBar(self):
        if self.titleBar is None:
            self.titleBar = QCustomTitleBar(self)

    def internalSetContents(self, widget, useContentsGeometry=True):
        if self.contents != None:
            if self.contents.parentWidget() == self:
                self.contents.setParent(None)

            self.layout.removeWidget(self.sizeGrip)
            self.layout.removeWidget(self.contents)
            self.layout.removeWidget(self.titleBar)
            self.contents.removeEventFilter(self)

            self.contents.windowTitleChanged.disconnect(self.setWindowTitle)
            self.contents.windowIconChanged.disconnect(self.onIconChange)

        self.contents = widget

        if self.contents != None:
            self.contents.setSizePolicy(QSizePolicy.Expanding,
                                        QSizePolicy.Expanding)
            if self.contents.testAttribute(QtCore.Qt.WA_QuitOnClose):
                self.contents.setAttribute(QtCore.Qt.WA_QuitOnClose, False)
                self.setAttribute(QtCore.Qt.WA_QuitOnClose)

            self.setAttribute(
                QtCore.Qt.WA_DeleteOnClose,
                self.contents.testAttribute(QtCore.Qt.WA_DeleteOnClose))

            self.setWindowTitle(self.contents.windowTitle())
            self.setWindowIcon(self.contents.windowIcon())

            self.contents.installEventFilter(self)

            self.contents.windowTitleChanged.connect(self.setWindowTitle)
            self.contents.windowIconChanged.connect(self.onIconChange)

            if useContentsGeometry:
                self.contents.show()
                self.setGeometry(self.contents.geometry())
                self.contents.setParent(self)
            else:
                self.contents.setParent(self)
                self.contents.show()

            self.updateWindowFlags()
            self.ensureTitleBar()

            self.layout.addWidget(self.titleBar)
            self.layout.addWidget(self.contents)

            if self.sizeGrip == None:
                self.sizeGrip = QSizeGrip(self)
                self.sizeGrip.setMaximumHeight(2)

            import sys
            if sys.platform == 'darwin':
                self.layout.addWidget(self.sizeGrip, 2)  # osx
            else:
                self.layout.addWidget(self.sizeGrip, 2, QtCore.Qt.AlignBottom
                                      | QtCore.Qt.AlignRight)  # window

        self.contentsChanged.emit(self.contents)

    # def nativeEvent ( self, eventType, message, result ):
    # 	if not self.titleBar:
    # 		return False
    # 	return super ().nativeEvent ( eventType, message, result )

    def event(self, e):
        if e.type() == QEvent.Show:
            if not self.contents.isVisibleTo(self):
                self.contents.show()
        if e.type() == QEvent.Hide:
            if self.contents != None:
                if self.contents.isVisibleTo(self) and self.windowState(
                ) != QtCore.Qt.WindowMinimized:
                    self.contents.hide()
        return super().event(e)

    def closeEvent(self, e):
        if self.contents != None and self.contents.isVisibleTo(self):
            if not self.contents.close():
                e.ignore()
        super().closeEvent(e)

    def changeEvent(self, e):
        if (e.type() == QEvent.WindowStateChange
                or e.type() == QEvent.ActivationChange
            ) and getMainWindow() and getMainWindow().windowState(
            ) == QtCore.Qt.WindowMinimized:
            getMainWindow().setWindowState(QtCore.Qt.WindowNoState)

        if self.titleBar != None:
            self.titleBar.updateWindowStateButtons()

        super().changeEvent(e)

    def eventFilter(self, o, e):
        if o == self.contents:
            if self.contents.parentWidget() == self:
                if e.type() == QEvent.Close:
                    self.close()
                elif e.type() == QEvent.HideToParent:
                    if self.isVisible():
                        self.hide()
                elif e.type() == QEvent.ShowToParent:
                    if not self.isVisible():
                        self.show()

        return super().eventFilter(o, e)

    def mouseReleaseEvent(self, e):
        if self.titleBar is None:
            e.ignore()
            return
        if e.button() == QtCore.Qt.LeftButton:
            self.titleBar.dragging = False

        super().mouseReleaseEvent(e)

    # def nudgeWindow ( self ):
    # 	pass

    def calcFrameWindowFlags(self):
        flags = self.windowFlags()

        if self.contents:
            # Get all window flags from contents, excluding WindowType flags.
            flags = (flags & QtCore.Qt.WindowType_Mask) | (
                self.contents.windowFlags() & ~QtCore.Qt.WindowType_Mask)

        import sys
        if sys.platform == 'darwin':
            return flags | QtCore.Qt.FramelessWindowHint  # osx FIXME: CustomizeWindowHint flag will show cocoa title bar.
        else:
            return flags | QtCore.Qt.FramelessWindowHint | QtCore.Qt.CustomizeWindowHint  # windows

    def updateWindowFlags(self):
        if self.contents != None:
            contentsWindowType = self.contents.windowFlags(
            ) & QtCore.Qt.WindowType_Mask
            # Contents has window type set, assign them it to us.
            if contentsWindowType != QtCore.Qt.Widget:
                # Clear window type flags
                self.setWindowFlags(self.windowFlags()
                                    & ~QtCore.Qt.WindowType_Mask)
                # Set window type from contents' flags, then clear contents' window type flags.
                self.setWindowFlags(self.windowFlags() | contentsWindowType)
                self.contents.setWindowFlags(self.windowFlags()
                                             & ~QtCore.Qt.WindowType_Mask)
            # No window type has been set on the contents, and we don't have any window flags
            elif (self.windowFlags()
                  & QtCore.Qt.WindowType_Mask) == QtCore.Qt.Widget:
                self.setWindowFlags(self.windowFlags() | QtCore.Qt.Window)

        self.setWindowFlags(self.calcFrameWindowFlags())

    def onIconChange(self):
        if self.contents != None and self.windowIcon().cacheKey(
        ) != self.contents.windowIcon().cacheKey():
            self.setWindowIcon(self.contents.windowIcon())

    def getResizeMargin(self):
        return self.resizeMargin

    def setResizeMargin(self, resizeMargin):
        self.resizeMargin = resizeMargin
class SegmentListItem(QFrame):
    def __init__(self, store, segment, is_selected, set_segment_end_frame_cb, clicked_cb, delete_cb):
        QFrame.__init__(self)
        self.segment = segment
        self.store = store
        self.set_segment_end_frame_cb = set_segment_end_frame_cb
        self.clicked_cb = clicked_cb
        self.start_frame = segment.start_frame
        self.end_frame = segment.end_frame
        self.is_selected = is_selected
        self.delete_cb = delete_cb
        self._init_ui()

    def mousePressEvent(self, event):
        self.clicked_cb(self.segment.id)
        QFrame.mousePressEvent(self, event)

    def _handle_set_end_frame(self):
        self.set_segment_end_frame_cb(self.segment.id)

    def _handle_delete(self):
        self.delete_cb(self.segment.id)

    def _on_label_click(self, text):
        self.store.set_video_frame(int(text))


    def _init_ui(self):
        self.layout = QBoxLayout(QBoxLayout.TopToBottom)
        self.frames_layout = QHBoxLayout()
        self.tags_layout = QHBoxLayout()
        self.tags_layout.setSpacing(0)
        self.tags_layout.setContentsMargins(0,0,0,0)

        self.start_frame_label = PressableLabel(str(self.start_frame), False, self._on_label_click)
        self.frame_separator = PressableLabel("-")
        self.frame_separator.setDisabled(True)

        self.end_container = QBoxLayout(QBoxLayout.LeftToRight)
        if not self.end_frame:
            self.end_button = QPushButton('End')
            self.end_container.setAlignment(Qt.AlignRight)
            self.end_container.addWidget(self.end_button)
            self.end_button.clicked.connect(self._handle_set_end_frame)
        else:
            self.end_widget = PressableLabel(str(self.end_frame), False, self._on_label_click)
            self.end_container.addWidget(self.end_widget)

        self.frames_layout.setSpacing(0)

        self.frames_layout.addWidget(self.start_frame_label)
        self.frames_layout.addWidget(self.frame_separator)

        if not self.end_frame:
            self.frames_layout.addStretch()

        self.frames_layout.addLayout(self.end_container)
        self.delete_cont = QBoxLayout(QBoxLayout.TopToBottom)
        self.delete = QPushButton('Del')
        self.delete_cont.addWidget(self.delete)
        self.delete_cont.setAlignment(Qt.AlignRight)
        self.frames_layout.addLayout(self.delete_cont)
        self.delete.clicked.connect(self._handle_delete)

        self.tags_layout.addWidget(PressableLabel('', True))
        for tag in self.segment.tags:
            self.tags_layout.addWidget(PressableLabel(tag.name, True))
        self.tags_layout.addStretch()

        self.layout.setContentsMargins(0,0,0,0)
        self.layout.addLayout(self.frames_layout)
        self.setLayout(self.layout)
        self.layout.addLayout(self.tags_layout)

        if self.is_selected:
            self.setProperty('class', 'selected')

        self._init_style()

    def _init_style(self):
        file = QFile(Registry.SEGMENT_LIST_ITEM_QSS);
        file.open(QFile.ReadOnly);
        styleSheet = file.readAll().data();
        self.setStyleSheet(styleSheet.decode("utf-8"));
Beispiel #25
0
class EditorWidget(QWidget):

    # Adding signal
    catCreated = pyqtSignal(Tag)
    catClicked = pyqtSignal(Tag)
    childClicked = pyqtSignal(str)

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

            self.stylesheet_filename = 'GUI/style/nodestyle.qss'
            self.loadStylesheet(self.stylesheet_filename)
            self.responseTable = None

            self.initUI(window)
        except Exception as ex:
            print("Exception caught in EditorWidget - __init__()")
            print(ex)
            handleError(ex)

    def initUI(self, window):
        try:
            self.layout = QBoxLayout(QBoxLayout.LeftToRight)
            self.layout.setContentsMargins(0, 0, 0, 0)
            self.setLayout(self.layout)

            # crate graphics scene
            self.scene = Scene()
            self.grScene = self.scene.grScene

            # create graphics view
            self.view = QDMGraphicsView(self.scene.grScene, self)
            self.layout.addWidget(self.view)
        except Exception as ex:
            print("Exception caught in EditorWidget - initUI()")
            print(ex)
            handleError(ex)


    
    # HACK: The function below was used for testing placement of nodes.
    #       Not needed for the program, might be helpful for debugging.
    # def addNodes(self):
    #     node1 = Node(self.scene, "My Awesome Node 1",
    #                  inputs=[0, 0, 0], outputs=[1])
    #     node2 = Node(self.scene, "My Awesome Node 2",
    #                  inputs=[3, 3, 3], outputs=[1])
    #     node3 = Node(self.scene, "My Awesome Node 3",
    #                  inputs=[2, 2, 2], outputs=[1])
    #     node4 = Node(self.scene, "A Category", inputs=[1, 1], outputs=[2, 2], )
    #     node1.setPos(-350, -250)
    #     node2.setPos(-75, 0)
    #     node3.setPos(200, -150)
    #     node4.setPos(200, -50)

    #     edge1 = Edge(
    #         self.scene, node1.outputs[0], node2.inputs[0], edge_type=EDGE_TYPE_BEZIER)
    #     edge2 = Edge(
    #         self.scene, node2.outputs[0], node3.inputs[0], edge_type=EDGE_TYPE_BEZIER)

    def addNode(self, title, inputs, outputs, posx, posy):
        try:
            node1 = Node(self.scene, title=title, inputs=inputs, outputs=outputs)
            node1.setPos(posx, posy)
        except Exception as ex:
            print("Exception caught in EditorWidget - addNode()")
            print(ex)
            handleError(ex)

    def updateNode(self, cat):
        try:
            if DEBUG: print("updating node in display")
            for node in self.scene.nodes:
                if node.category.cat_id == cat.cat_id:
                    if DEBUG: print("found node to update")
                    node.category = cat
                    if DEBUG: print(str(node.category))
                    
                    # Displaying updated content on node.
                    node.content.wdg_label.clear()
                    node.content.wdg_label.displayVisuals(cat)
        except Exception as ex:
            print("EXCEPTION CAUGHT! In EditorWidget - updateNode()")
            print(ex)
            handleError(ex)


    def addDebugContent(self):
        try:
            greenBrush = QBrush(Qt.green)
            outlinePen = QPen(Qt.black)
            outlinePen.setWidth(2)

            rect = self.grScene.addRect(-100, -100, 80,
                                        100, outlinePen, greenBrush)
            rect.setFlag(QGraphicsItem.ItemIsMovable)

            text = self.grScene.addText(
                "This is my Awesome text!", QFont("Ubuntu"))
            text.setFlag(QGraphicsItem.ItemIsSelectable)
            text.setFlag(QGraphicsItem.ItemIsMovable)
            text.setDefaultTextColor(QColor.fromRgbF(1.0, 1.0, 1.0))

            widget1 = QPushButton("Hello World")
            proxy1 = self.grScene.addWidget(widget1)
            proxy1.setFlag(QGraphicsItem.ItemIsMovable)
            proxy1.setPos(0, 30)

            widget2 = QTextEdit()
            proxy2 = self.grScene.addWidget(widget2)
            proxy2.setFlag(QGraphicsItem.ItemIsSelectable)
            proxy2.setPos(0, 60)

            line = self.grScene.addLine(-200, -200, 400, -100, outlinePen)
            line.setFlag(QGraphicsItem.ItemIsMovable)
            line.setFlag(QGraphicsItem.ItemIsSelectable)
        except Exception as ex:
            print("Exception caught in EditorWidget - addDebugContent()")
            print(ex)
            handleError(ex)

    def loadStylesheet(self, filename):
        try:
            if DEBUG: print('STYLE loading:', filename)
            file = QFile(filename)
            file.open(QFile.ReadOnly | QFile.Text)
            stylesheet = file.readAll()
            QApplication.instance().setStyleSheet(str(stylesheet, encoding='utf-8'))
        except Exception as ex:
            print("Exception caught in EditorWidget - loadStylesheet()")
            print(ex)
            handleError(ex)


    """
    Determine if the condition or random table has text afterwards.
    """
    def tableContainsTail(self, template):
        try:
            for tag in reversed(template.tags):
                if DEBUG: print("Beginning of loop")
                if DEBUG: print(f"Current tag: {tag}")

                if isinstance(tag, str) is True:
                    if DEBUG: print("String found before Condition or Random. Return True.")
                    return True, tag
                # Check for <oob> tag
                elif tag.type == "oob":
                    if DEBUG: print("oob found, keep searching.")
                elif tag.type == "condition" or tag.type == "random":
                    if DEBUG: print("Condition or Random found before String. Return False.")
                    return False, None
            # Made it to end without finding anything
            if DEBUG: print("Made it to end without finding anything. This should not happen!")
            return False, None
        except Exception as ex:
            print("Exception caught in EditorWidget - tableContainsTail_better()")
            print(ex)
            handleError(ex)


    """
    Function to find the sentence to be used for <that> tag of potential children.
    Returns a list of strings of last sentences in the <template> tag.
        Sentences will only contain more than 1 element if there is a <random> or
        <condition> tag. Sentences will then have a string for each <li> tag.
    """
    def getLastSentence(self, cat):
        if DEBUG: print("In getLastSentence()")
        try:
            template = cat.findTag("template")
            sentences = []
            if template is None:
                if DEBUG: print("Template is empty")
                return None
            condition = template.findTag("condition")
            random = template.findTag("random")
            if DEBUG: print("Before logic")
            if condition is None and random is None:
                if DEBUG: print("no random or condition tag found in template")
                if DEBUG: print(str(template))
                tempString = template.findTag("text")
                if DEBUG: print(f"tempString: {tempString}")
                if tempString is None:
                    if DEBUG: print("No sentence in category")
                    return None
                tempArr = tempString.split()
                index = 0
                for word in reversed(tempArr):
                    if "." in word or "?" in word or "!" in word:
                        if index == 0:
                            if DEBUG: print("Found last punctuation mark on very first word. Keep searching.")
                            if DEBUG: print(word)
                        else:
                            if DEBUG: print("Found the start of the last sentence")
                            if DEBUG: print(word)
                            arrSize = len(tempArr)
                            start = arrSize - (index)
                            lastSentence = tempArr[start:arrSize]
                            lastSentence = " ".join(lastSentence)
                            if DEBUG: print(f"appending: {lastSentence}")
                            sentences.append(lastSentence)
                    index = index + 1

                # If made it to end of array without finding another punctiation mark. return full text in template
                if len(sentences) is 0:
                    if DEBUG: print(f"appending: {tempString}")
                    sentences.append(tempString)
                return sentences
            else:
                if DEBUG: print("template contains either a random or condition tag")
                if DEBUG: print(str(template))
                contains_tail, tail = self.tableContainsTail(template)
                if contains_tail is True:
                    sentences.append(tail)
                    return sentences
                else:
                    if DEBUG: print("Random or Condition tag is the last thing in the template")
                    if condition is not None:
                        if DEBUG: print("table contains condition table")
                        for li in condition.tags:
                            liText = li.findTag("text")
                            if DEBUG: print("text inside condition: " + liText)
                            liArr = liText.split()
                            index = 0
                            punctuationExists = False
                            for word in reversed(liArr):
                                if "." in word or "?" in word or "!" in word:
                                    if index == 0:
                                        if DEBUG:print("Found last punctuation mark on very first word. Keep searching.")
                                        if DEBUG: print(word)
                                    else:
                                        if DEBUG: print("Found the start of the last sentence")
                                        if DEBUG: print(word)
                                        arrSize = len(liArr)
                                        start = arrSize - (index)
                                        lastSentence = liArr[start:arrSize]
                                        lastSentence = " ".join(lastSentence)
                                        if DEBUG: print(f"appending: {lastSentence}")
                                        sentences.append(lastSentence)
                                        punctuationExists = True
                                        break
                                index = index + 1
                            # If made it to end of array without finding another punctiation mark. return full text in tag
                            if punctuationExists is False:
                                sentences.append(liText)
                        return sentences
                        if DEBUG: print("done goofed")
                    else:
                        if DEBUG: print("table contains random table")
                        for li in random.tags:
                            liText = li.findTag("text")
                            if DEBUG: print("text inside random: " + liText)
                            liArr = liText.split()
                            index = 0
                            punctuationExists = False
                            for word in reversed(liArr):
                                if "." in word or "?" in word or "!" in word:
                                    if index == 0:
                                        if DEBUG: print("Found last punctuation mark on very first word. Keep searching.")
                                        if DEBUG: print(word)
                                    else:
                                        if DEBUG: print("Found the start of the last sentence")
                                        if DEBUG: print(word)
                                        arrSize = len(liArr)
                                        start = arrSize - (index)
                                        lastSentence = liArr[start:arrSize]
                                        lastSentence = " ".join(lastSentence)
                                        if DEBUG: print(f"appending: {lastSentence}")
                                        sentences.append(lastSentence)
                                        punctuationExists = True
                                        break
                                index = index + 1
                            # If at the end of array without finding another punctiation mark. return full text in tag
                            if punctuationExists is False:
                                if DEBUG: print(f"appending: {liText}")
                                sentences.append(liText)
                        return sentences
                    if DEBUG: print("done goofed")
        except Exception as ex:
            print("Exception caught in EditorWidget - getLastSentence()")
            print(ex)
            handleError(ex)

    """
    Find child nodes in the scene and add edges based off of <that> tags
    """
    def findChildNodes(self, newnode, thatStr):
        try:
            if DEBUG: print("looking for child nodes")
            xOffset = 0
            for node in self.scene.nodes:
                thatTag = node.category.findTag("that")
                if DEBUG: print(f"Current Category:\n{node.category}")
                if DEBUG: print(f"that: {str(thatTag)}")
                if newnode == node:
                    if DEBUG: print("looking at node just created. Do nothing")
                elif thatTag is None:
                    if DEBUG: print("no that tag found in category: " + str(node.category))
                else:
                    # That tag was found, add an edge
                    if DEBUG: print("that tag was found in category: " + str(node.category))
                    thatText = thatTag.findTag("text")
                    if DEBUG: print(f"Return type of findTag(\"text\"): {type(thatText)}")
                    if DEBUG: print(f"{thatText}")
                    if DEBUG: print(f"Data type of parameter thatStr: {type(thatStr)}")
                    if DEBUG: print(f"{thatStr}")
                    if thatText.lower() == thatStr.lower():
                        if DEBUG: print("FOUND CHILD!")
                        self.updateChildSockets(newnode, node)
                    else:
                        if DEBUG: print("Not a match for a child")

            if DEBUG: print("No child found in scene")
        except Exception as ex:
            print("Exception caught in EditorWidget when looking for child nodes")
            print(ex)
            handleError(ex)


    """
    Find parent nodes in the scene and add edges based off of <that> tags.
    """
    def findParentNodes(self, newnode):
        try:
            if DEBUG: print("looking for parent nodes")
            mythatTag = newnode.category.findTag("that")
            if mythatTag is None:
                if DEBUG: print("no that tag so node will not have any parents")
                return
            thatText = mythatTag.findTag("text")
            if DEBUG: print("Text of That Tag to look for: " + thatText)
            xOffset = 0
            for node in self.scene.nodes:
                if node == newnode:
                    if DEBUG: print("looking at node just created, do nothing")
                else:
                    if DEBUG: print("looking at node with category: " + str(node.category))
                    self.updateParentSockets(newnode, node, thatText)
        except Exception as ex:
            print("Exception caught in EditorWidget - findParentNodes()")
            print(ex)
            handleError(ex)

    
    """
    Function to update the edges connecting to child nodes.
    """
    def updateChildSockets(self, newnode, node):
        try:
            parentsocket = Socket(newnode, position=RIGHT_BOTTOM, socket_type=2)
            newnode.inputs.append(parentsocket) # outputs is children

            if node not in newnode.children:
                newnode.children.append(node)

            childsocket = Socket(node)
            node.outputs.append(childsocket)

            if newnode not in node.parents:
                node.parents.append(newnode)

            edge = Edge(self.scene, parentsocket, childsocket)
            
            return edge
        except Exception as ex:
            print("Exception caught in EditorWidget - updateChildSockets()")
            print(ex)
            handleError(ex)


    """
    Function to update the edges connecting to parent nodes.
    """
    def updateParentSockets(self, newnode, node, thatText):
        try:
            templateText = self.getLastSentence(node.category)
            for text in templateText:
                if thatText.lower() == text.lower():
                    if DEBUG: print("Found parent node!")
                    parentsocket = Socket(node, position=RIGHT_BOTTOM, socket_type=2)
                    node.inputs.append(parentsocket)

                    # need to check if node exists in list before appending
                    if newnode not in node.children:
                        node.children.append(newnode)

                    childsocket = Socket(newnode)
                    newnode.outputs.append(childsocket)

                    if node not in newnode.parents:
                        newnode.parents.append(node)

                    edge = Edge(self.scene, parentsocket, childsocket)
                else:
                    if DEBUG: print("Not a match for a parent")
        except Exception as ex:
            print("Exception caught in EditorWidget - updateParentSockets()")
            print(ex)
            handleError(ex)
  

    """
    Function to organize nodes based on parents and children
    """
    def placeNodes(self, nodes, depth=0, yOffset=0):
        # TODO: Recursively look through children. place parents on left, children on the right.
        try:
            if DEBUG: print("placing nodes")
            if depth > 5:
                if DEBUG: print("reached max depth")
                return

            xOffset = 500
            
            for node in nodes:
                if len(node.parents) is 0:
                    if DEBUG: print("node has no parents place to the left.")
                    if DEBUG: print(f"Placing category:\n{node.category}")
                    node.setPos(-900, -900 + yOffset)
                    yOffset += 575
                else:
                    if DEBUG: print("node has parents")
                    yOffset = 0
                    for child in node.children:
                        depth = depth + 1
                        y = node.grNode.y()
                        child.setPos(xOffset, y + yOffset)
                        xOffset += 200
                        yOffset += 575
                        if DEBUG: print(f"Placing category:\n{node.category}")
                        self.placeNodes(child.children, depth, yOffset)
                    node.setPos(xOffset, yOffset)
                    xOffset += 300
        except Exception as ex:
            print("Exception caught placing nodes!")
            print(ex)
            handleError(ex)

    # @pyqtSlot(Tag)
    # def addChildClicked(self, cat):
    #     try:
    #         if DEBUG: print("In slot of editor widget")
    #         template = cat.findTag("template")
    #         if DEBUG: print("template tags list: " + str(template.tags))
    #         if template.findTag("condition") is None and template.findTag("random") is None:
    #             if DEBUG: print("no table inside template")
    #             thatStr = self.getLastSentence(cat)
    #             if DEBUG: print(thatStr)
    #             self.childClicked.emit(thatStr[0])  # emitting to Editor Window
    #         else:
    #             if self.tableContainsTail(template) is False:
    #                 if DEBUG: print("table is last thing in template. Must choose response to use for that")
    #                 template = cat.findTag("template")
    #                 condition = template.findTag("condition")
    #                 random = template.findTag("random")
    #                 if condition is not None:
    #                     if DEBUG: print("create response table out of condition items")
    #                     self.responseTable = ResponseSelection(tag=condition, category=cat, editspace=self)
    #                 else:
    #                     if DEBUG: print("create response table out of random items")
    #                     self.responseTable = ResponseSelection(tag=random, category=cat, editspace=self)
    #             else:
    #                 if DEBUG: print("table contains tail, there is only one possible sentence to use for that")
    #                 thatStr = self.getLastSentence(cat)
    #                 if DEBUG: print(thatStr[0])
    #                 self.childClicked.emit(thatStr[0]) # emitting to Editor Window
    #     except Exception as ex:
    #         print(ex)
    #         handleError(ex)

    def setNodeStyleSheet(self, node):
        node.content.setStyleSheet(self.stylesheet_filename)
        return node

    @pyqtSlot(Tag)
    def categoryClicked(self, cat):
        if DEBUG: print("slot in EditorWidget - categoryClicked()")
        
        # Resetting all nodes to original style sheet
        self.scene.nodes = list(map(self.setNodeStyleSheet, self.scene.nodes))
        
        try:
            # FIXME: Optimize by maybe place parent and children nodes in something other than lists.
            for node in self.scene.nodes:
                if DEBUG: print("Searching for correct node")
                if node.category.cat_id == cat.cat_id:
                    node.content.setStyleSheet("QDMNodeContentWidget { background: #ffff1a; }")
                    for child in node.children:
                        if DEBUG: print("Changing background of child")
                        child.content.setStyleSheet("QDMNodeContentWidget { background: #f82f04; }")

                    for parent in node.parents:
                        if DEBUG: print("Changing background of parent")
                        parent.content.setStyleSheet("QDMNodeContentWidget { background: #0cfdd8; }")
            
            self.catClicked.emit(cat) # emitting signal to be sent to EditorWindow
        except Exception as ex:
            print("Exception caught when category is clicked.")
            print(ex)
            handleError(ex)
Beispiel #26
0
class Controls(QFrame):
    def __init__(self, store, pause_cb, next_cb, prev_cb, seek_cb,
                 frames_to_jump_cb, jump_back_cb, jump_forward_cb):
        QFrame.__init__(self)
        self.store = store
        self.pause_cb = pause_cb
        self.next_cb = next_cb
        self.prev_cb = prev_cb
        self.seek_cb = seek_cb
        self.frames_to_jump_cb = frames_to_jump_cb
        self.jump_back_cb = jump_back_cb
        self.jump_forward_cb = jump_forward_cb
        self._paused = True

        self.store.video_frame_number_changed.connect(
            self._video_frame_number_changed)

        self._init_ui()

    def _video_frame_number_changed(self, frame_number):
        self.slider.blockSignals(True)

        self._update_slider(frame_number)
        self._update_times(frame_number)
        self._update_frames(frame_number)

        self.slider.blockSignals(False)

    def _jump_back_clicked(self):
        self.jump_back_cb()

    def _jump_forward_clicked(self):
        self.jump_forward_cb()

    def _on_frames_to_jump_change(self, text):
        try:
            int(text)
        except ValueError:
            return

        self.frames_to_jump_cb(int(text))

    def _next_clicked(self):
        self.next_cb()

    def _prev_clicked(self):
        self.prev_cb()

    def _slider_changed(self):
        self.seek_cb(self.slider.value())

    def _update_slider(self, frame_number):
        self.slider.setValue(
            float(frame_number) / self.store.video_total_frames * 16384)

    def _update_times(self, frame_number):
        self.time_start_label.setText(format_frames_to_hms(frame_number))
        self.time_end_label.setText(
            format_frames_to_hms(self.store.video_total_frames))

    def _update_frames(self, frame_number):
        self.frame_start_label.setText(str(frame_number))
        self.frame_end_label.setText(str(self.store.video_total_frames - 1))

    def _init_ui(self):
        self.layout = QBoxLayout(QBoxLayout.LeftToRight)
        self.left_controls_layout = QVBoxLayout()
        self.left_controls_layout.setContentsMargins(0, 0, 0, 0)

        self.play_controls_frame = QFrame()
        self.play_controls_layout = QHBoxLayout()
        self.play_controls_layout.setContentsMargins(0, 0, 0, 0)
        self.play_controls_frame.setLayout(self.play_controls_layout)

        self.custom_controls_layout = QHBoxLayout()
        self.custom_controls_frame = QFrame()
        self.custom_controls_layout.setContentsMargins(0, 0, 0, 0)
        self.custom_controls_frame.setLayout(self.custom_controls_layout)
        self.left_controls_layout.addWidget(self.play_controls_frame)
        self.left_controls_layout.addWidget(self.custom_controls_frame)
        self.custom_controls_layout.setAlignment(Qt.AlignCenter)

        self.right_slider_layout = QBoxLayout(QBoxLayout.TopToBottom)
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setMaximum(16384)
        self.slider.setMinimum(0)
        self.slider.setSingleStep(1)
        self.slider.setTickInterval(1)
        self.right_slider_layout.setContentsMargins(0, 0, 0, 0)
        self.label_layout = QHBoxLayout()
        self.time_start_label = QLabel("")
        self.time_end_label = QLabel("")
        self.label_layout.addWidget(self.time_start_label)
        self.label_layout.addWidget(self.time_end_label)
        self.label_layout.setContentsMargins(0, 0, 0, 0)
        self.time_start_label.setContentsMargins(0, 0, 0, 0)
        self.time_start_label.setAlignment(Qt.AlignLeft | Qt.AlignTop)
        self.time_end_label.setAlignment(Qt.AlignRight | Qt.AlignTop)
        self.time_end_label.setContentsMargins(0, 0, 0, 0)
        self.right_slider_layout.addWidget(self.slider)
        self.right_slider_layout.addLayout(self.label_layout)

        self.frame_label_layout = QHBoxLayout()
        self.frame_start_label = QLabel("")
        self.frame_end_label = QLabel("")
        self.frame_start_label.setAlignment(Qt.AlignLeft | Qt.AlignTop)
        self.frame_end_label.setAlignment(Qt.AlignRight | Qt.AlignTop)
        self.frame_label_layout.addWidget(self.frame_start_label)
        self.frame_label_layout.addWidget(self.frame_end_label)
        self.right_slider_layout.addLayout(self.frame_label_layout)

        self.prev = QPushButton()
        self.prev.setMaximumWidth(75)
        self.prev.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSeekBackward))

        self.next = QPushButton()
        self.next.setMaximumWidth(75)
        self.next.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSeekForward))

        self.custom_back = QPushButton()
        self.custom_back.setMaximumWidth(75)
        self.custom_back.setContentsMargins(0, 0, 0, 0)
        self.custom_back.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSeekBackward))

        self.custom_frames = FrameLineEdit()
        self.custom_frames.setMaximumWidth(50)
        self.custom_frames.setMinimumWidth(50)
        self.custom_frames.setAttribute(Qt.WA_MacShowFocusRect, 0)
        self.custom_frames.setContentsMargins(0, 0, 0, 0)
        self.custom_frames.setText(str(self.store.frames_to_jump))
        self.custom_frames.setAlignment(Qt.AlignCenter)
        self.custom_frames.setValidator(QIntValidator(0, 999, self))
        self.custom_frames.textChanged.connect(self._on_frames_to_jump_change)
        self.custom_frames.focusOutEvent
        self.custom_frames_container = QFrame()
        self.custom_frames_container_layout = QVBoxLayout()
        self.custom_frames_container_layout.addWidget(self.custom_frames)
        self.custom_frames_container_layout.setContentsMargins(0, 0, 0, 0)
        self.custom_frames_container.setLayout(
            self.custom_frames_container_layout)

        self.custom_fwd = QPushButton()
        self.custom_fwd.setMaximumWidth(75)
        self.custom_fwd.setContentsMargins(0, 0, 0, 0)
        self.custom_fwd.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSeekForward))

        self.custom_controls_layout.addStretch()
        self.custom_controls_layout.addWidget(self.custom_back)
        self.custom_controls_layout.addWidget(self.custom_frames_container)
        self.custom_controls_layout.addWidget(self.custom_fwd)
        self.custom_controls_layout.addStretch()

        self.play_controls_layout.addStretch()
        self.play_controls_layout.addWidget(self.prev)
        self.play_controls_layout.addWidget(self.next)
        self.play_controls_layout.addStretch()
        self.layout.addLayout(self.left_controls_layout, 1)
        self.layout.addLayout(self.right_slider_layout, 4)

        self.setLayout(self.layout)

        self.next.clicked.connect(self._next_clicked)
        self.prev.clicked.connect(self._prev_clicked)
        self.slider.valueChanged.connect(self._slider_changed)
        self.custom_back.clicked.connect(self._jump_back_clicked)
        self.custom_fwd.clicked.connect(self._jump_forward_clicked)

        self._init_style()

    def _init_style(self):
        file = QFile(Registry.CONTROLS_QSS)
        file.open(QFile.ReadOnly)
        styleSheet = file.readAll().data()
        self.setStyleSheet(styleSheet.decode("utf-8"))
Beispiel #27
0
window = QWidget()

btn1 = QPushButton("One")
btn2 = QPushButton("Two")
btn3 = QPushButton("Three")

# Set the layout

box = QBoxLayout(QBoxLayout.Direction(0))  # TODO

box.addWidget(btn1)
box.addWidget(btn2)
box.addWidget(btn3)

box.setContentsMargins(0, 0, 0,
                       0)  # set the spacing around the layout (in pixels)
box.setSpacing(0)  # set the spacing between elements (in pixels)

window.setLayout(box)

# Show
window.show()

# The mainloop of the application. The event handling starts from this point.
# The exec_() method has an underscore. It is because the exec is a Python keyword. And thus, exec_() was used instead.
exit_code = app.exec_()

# The sys.exit() method ensures a clean exit.
# The environment will be informed, how the application ended.
sys.exit(exit_code)
    def initUI(self, title):

        ### Add toolbar to widget ###

        toolLayout = QBoxLayout(QBoxLayout.TopToBottom, self)
        toolLayout.setContentsMargins(0, 0, 0, 0)

        toolbar = QToolBar()
        toolLayout.addWidget(toolbar)

        ### Add contents ###

        vbox = QVBoxLayout()

        self.label = QLabel(self)
        self.label.setText(title)
        vbox.addWidget(self.label)

        self.list = QListWidget(self)
        self.list.setSelectionMode(
            self.list.ExtendedSelection)  #MultiSelection?
        self.list.setIconSize(QSize(60, 60))
        #self.list.setFlow( QListWidget.LeftToRight )
        #self.list.setResizeMode( QListWidget.Adjust ) # TODO: Finish QListWidget settings
        #self.list.setSpacing( 2 )
        #self.list.setViewMode( QListWidget.IconMode )
        vbox.addWidget(self.list)

        ### Put contents in outer toolLayout ###

        toolLayout.addLayout(vbox)
        toolLayout.setDirection(QBoxLayout.BottomToTop)

        ### Tools ###

        cwd = os.path.abspath(os.path.dirname(__file__))
        icons = os.path.join(cwd, 'icons')

        select_all_act = QtHelper.initAction(
            self,
            'Select All',
            self.selectAll,
            status='Select all images in the image set',
            icon='Select All.png')
        toolbar.addAction(select_all_act)

        toolbar.addSeparator()

        open_act = QtHelper.initAction(self,
                                       'Add Images',
                                       self.selectImages,
                                       status='Add images to the image set',
                                       icon='Images.png')
        toolbar.addAction(open_act)

        remove_act = QtHelper.initAction(
            self,
            'Remove Selected Images',
            self.removeSelected,
            status='Remove selected images from the image set',
            icon='Delete.png')
        toolbar.addAction(remove_act)
Beispiel #29
0
class Demo(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("测试")
        # 窗口大小
        self.resize(1400, 800)
        # self.setFixedSize(1500, 600)  # 设置窗口为固定尺寸, 此时窗口不可调整大小
        # self.setMinimumSize(1800, 1000)  # 设置窗口最大尺寸
        # self.setMaximumSize(900, 300)  # 设置窗口最小尺寸
        # self.setWindowFlag(Qt.WindowStaysOnTopHint)   # 设置窗口顶层显示
        # self.setWindowFlags(Qt.FramelessWindowHint)  # 设置无边框窗口样式,不显示最上面的标题栏

        self.content_font = QFont("微软雅黑", 12, QFont.Medium)  # 定义字体样式

        self.center()

        self.__setup_ui__()

    # 控制窗口显示在屏幕中心的方法

    def center(self):
        # 获得窗口
        qr = self.frameGeometry()
        # 获得屏幕中心点
        cp = QDesktopWidget().availableGeometry().center()
        # 显示到屏幕中心
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    # 关闭窗口的时候,触发了QCloseEvent,需要重写closeEvent()事件处理程序,这样就可以弹出是否退出的确认窗口
    def closeEvent(self, event):
        reply = QMessageBox.question(
            self,
            "退出程序",  # 提示框标题
            "确定退出xxxx程序吗?",  # 消息对话框中显示的文本
            QMessageBox.Yes | QMessageBox.No,  # 指定按钮的组合 Yes和No
            QMessageBox.No  # 默认的按钮焦点,这里默认是No按钮
        )
        # 判断按钮的选择
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

    def __setup_ui__(self):
        # 工具栏
        self.frame_tool = QFrame(self)
        self.frame_tool.setObjectName("frame_tool")
        self.frame_tool.setGeometry(0, 0, self.width(), 25)
        self.frame_tool.setStyleSheet("border-color: rgb(0, 0, 0);")
        self.frame_tool.setFrameShape(QFrame.Panel)
        self.frame_tool.setFrameShadow(QFrame.Raised)

        # 1.1 界面1按钮
        self.window1_btn = QToolButton(self.frame_tool)
        self.window1_btn.setCheckable(True)
        self.window1_btn.setText("window1")
        self.window1_btn.setObjectName("menu_btn")
        self.window1_btn.resize(100, 25)
        self.window1_btn.clicked.connect(self.click_window1)
        self.window1_btn.setAutoRaise(
            True)  # 去掉工具按钮的边框线如果是QPushButton按钮的话,就是用setFlat(True)这个方法,用法相同

        # 1.2 界面2按钮
        self.window2_btn = QToolButton(self.frame_tool)
        self.window2_btn.setCheckable(True)
        self.window2_btn.setText("window2")
        self.window2_btn.setObjectName("menu_btn")
        self.window2_btn.resize(100, 25)
        self.window2_btn.move(self.window1_btn.width(), 0)
        self.window2_btn.clicked.connect(self.click_window2)
        self.window2_btn.setAutoRaise(True)

        self.btn_group = QButtonGroup(self.frame_tool)
        self.btn_group.addButton(self.window1_btn, 1)
        self.btn_group.addButton(self.window2_btn, 2)

        # 1.3 帮助下拉菜单栏
        # 创建帮助工具按钮
        help_btn = QToolButton(self.frame_tool)
        help_btn.setText("帮助")
        help_btn.setObjectName("menu_btn")
        help_btn.resize(100, 25)
        help_btn.move(self.window2_btn.x() + self.window2_btn.width(), 0)
        help_btn.setAutoRaise(True)
        help_btn.setPopupMode(QToolButton.InstantPopup)
        # 创建关于菜单
        help_menu = QMenu("帮助", self.frame_tool)
        feedback_action = QAction(QIcon("xxx.png"), "反馈", help_menu)
        feedback_action.triggered.connect(self.click_feedback)
        about_action = QAction(QIcon("xxx.png"), "关于", help_menu)
        about_action.triggered.connect(self.click_about)
        # 把两个QAction放入help_menu
        help_menu.addAction(feedback_action)
        help_menu.addAction(about_action)
        # 把help_menu放入help_btn
        help_btn.setMenu(help_menu)

        # 2. 工作区域
        self.main_frame = QFrame(self)
        self.main_frame.setGeometry(0, 25, self.width(),
                                    self.height() - self.frame_tool.height())
        # self.main_frame.setStyleSheet("background-color: rgb(65, 95, 255)")

        # 创建堆叠布局
        self.stacked_layout = QStackedLayout(self.main_frame)

        # 第一个布局
        self.main_frame1 = QMainWindow()
        self.frame1_bar = QStatusBar()
        self.frame1_bar.setObjectName("frame1_bar")
        self.main_frame1.setStatusBar(self.frame1_bar)
        self.frame1_bar.showMessage("欢迎进入frame1")

        rom_frame = QFrame(self.main_frame1)
        rom_frame.setGeometry(0, 0, self.width(),
                              self.main_frame.height() - 25)
        rom_frame.setFrameShape(QFrame.Panel)
        rom_frame.setFrameShadow(QFrame.Raised)

        # 超链接
        self.super_link = QLabel(rom_frame)
        self.super_link.setText("""
            超链接: <a href="https://blog.csdn.net/s_daqing">点击打开查看</a>
            """)
        self.super_link.setGeometry(20, 30, 300, 25)
        self.super_link.setFont(self.content_font)  # 使用字体样式
        self.super_link.setOpenExternalLinks(True)  # 使其成为超链接
        self.super_link.setTextInteractionFlags(
            Qt.TextBrowserInteraction)  # 双击可以复制文本

        self.start_btn = QPushButton("开 始", rom_frame)
        self.start_btn.setGeometry(self.width() * 0.7,
                                   self.height() * 0.8, 100, 40)
        # self.start_btn.clicked.connect(self.start_btn_click)
        self.quit_btn = QPushButton("退 出", rom_frame)
        self.quit_btn.setGeometry(self.width() * 0.85,
                                  self.height() * 0.8, 100, 40)
        self.quit_btn.setStatusTip("点击关闭程序")
        # self.quit_btn.clicked.connect(QCoreApplication.instance().quit)  # 点击退出可以直接退出
        self.quit_btn.clicked.connect(self.close)  # 点击退出按钮的退出槽函数

        #rom_frame1 = QFrame()
        #rom_frame1.setFrameShape(QFrame.Panel)
        #rom_frame1.setFrameShadow(QFrame.Raised)

        #rom_frame2 = QFrame()
        #rom_frame2.setFrameShape(QFrame.Panel)
        #rom_frame2.setFrameShadow(QFrame.Raised)

        # 创建布局管理器
        self.layout1 = QBoxLayout(QBoxLayout.TopToBottom)

        # 给管理器对象设置父控件
        rom_frame.setLayout(self.layout1)
        self.main_frame1.setCentralWidget(rom_frame)

        # 把子控件添加到布局管理器中
        #self.layout1.addWidget(rom_frame1, 1)
        #self.layout1.addWidget(rom_frame2, 1)

        self.layout1.setContentsMargins(0, 0, 0, 0)  # 设置布局的左上右下外边距
        self.layout1.setSpacing(0)  # 设置子控件的内边距

        frame1_bar_frame = QFrame(self.main_frame1)
        frame1_bar_frame.setGeometry(0, self.main_frame.height(), self.width(),
                                     25)

        # 第二个布局
        self.main_frame2 = QMainWindow()
        self.frame2_bar = QStatusBar()
        self.frame2_bar.setObjectName("frame2_bar")
        self.main_frame2.setStatusBar(self.frame2_bar)
        self.frame2_bar.showMessage("欢迎进入frame2")

        custom_frame = QFrame(self.main_frame2)
        custom_frame.setGeometry(0, 0, self.width(),
                                 self.main_frame.height() - 25)
        custom_frame.setFrameShape(QFrame.Panel)
        custom_frame.setFrameShadow(QFrame.Raised)

        custom_frame1 = QFrame()
        custom_frame1.setFrameShape(QFrame.Panel)
        custom_frame1.setFrameShadow(QFrame.Raised)

        custom_frame2 = QFrame()
        custom_frame2.setFrameShape(QFrame.Panel)
        custom_frame2.setFrameShadow(QFrame.Raised)

        custom_frame3 = QFrame()
        custom_frame3.setFrameShape(QFrame.Panel)
        custom_frame3.setFrameShadow(QFrame.Raised)

        # 创建布局管理器
        self.layout2 = QBoxLayout(QBoxLayout.TopToBottom)

        # 给管理器对象设置父控件
        custom_frame.setLayout(self.layout2)
        """
        使用了父类为QMainWindow的话,在里面使用布局类,QGridLayout, QHBoxLayout ,QVBoxLayout 等等时,发现不好用,
        加上下面这句代码就可以了,QMainWindow对象.setCentralWidget(这里填布局管理器的父控件对象)
        """
        self.main_frame2.setCentralWidget(custom_frame)

        # 把子控件添加到布局管理器中
        self.layout2.addWidget(custom_frame1, 1)
        self.layout2.addWidget(custom_frame2, 1)
        self.layout2.addWidget(custom_frame3, 1)

        self.layout2.setContentsMargins(0, 0, 0, 0)  # 设置布局的左上右下外边距
        self.layout2.setSpacing(0)  # 设置子控件的内边距

        frame2_bar_frame = QFrame(self.main_frame2)
        frame2_bar_frame.setGeometry(0, self.main_frame.height(), self.width(),
                                     25)

        # 把两个布局放进去
        self.stacked_layout.addWidget(self.main_frame1)
        self.stacked_layout.addWidget(self.main_frame2)

    def click_window1(self):
        if self.stacked_layout.currentIndex() != 0:
            self.stacked_layout.setCurrentIndex(0)
            self.frame1_bar.showMessage("欢迎进入frame1")

    def click_window2(self):
        if self.stacked_layout.currentIndex() != 1:
            self.stacked_layout.setCurrentIndex(1)
            self.frame2_bar.showMessage("欢迎进入frame2")
            QDesktopServices.openUrl(QUrl("https://www.csdn.net/")
                                     )  # 点击window2按钮后,执行这个槽函数的时候,会在浏览器自动打开这个网址

    def click_feedback(self, event):
        QMessageBox.about(self, "反馈",
                          "使用过程中如有疑问,请联系:xxxx.163.com\r\n\r\n版本:V1.0.1")

    def click_about(self, event):
        QMessageBox.about(self, "关于", "使用文档,请参考:xxxxxx")
Beispiel #30
0
class E5SideBar(QWidget):
    """
    Class implementing a sidebar with a widget area, that is hidden or shown,
    if the current tab is clicked again.
    """
    Version = 1
    
    North = 0
    East = 1
    South = 2
    West = 3
    
    def __init__(self, orientation=None, delay=200, parent=None):
        """
        Constructor
        
        @param orientation orientation of the sidebar widget (North, East,
            South, West)
        @param delay value for the expand/shrink delay in milliseconds
            (integer)
        @param parent parent widget (QWidget)
        """
        super(E5SideBar, self).__init__(parent)
        
        self.__tabBar = QTabBar()
        self.__tabBar.setDrawBase(True)
        self.__tabBar.setShape(QTabBar.RoundedNorth)
        self.__tabBar.setUsesScrollButtons(True)
        self.__tabBar.setDrawBase(False)
        self.__stackedWidget = QStackedWidget(self)
        self.__stackedWidget.setContentsMargins(0, 0, 0, 0)
        self.__autoHideButton = QToolButton()
        self.__autoHideButton.setCheckable(True)
        self.__autoHideButton.setIcon(
            UI.PixmapCache.getIcon("autoHideOff.png"))
        self.__autoHideButton.setChecked(True)
        self.__autoHideButton.setToolTip(
            self.tr("Deselect to activate automatic collapsing"))
        self.barLayout = QBoxLayout(QBoxLayout.LeftToRight)
        self.barLayout.setContentsMargins(0, 0, 0, 0)
        self.layout = QBoxLayout(QBoxLayout.TopToBottom)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(0)
        self.barLayout.addWidget(self.__autoHideButton)
        self.barLayout.addWidget(self.__tabBar)
        self.layout.addLayout(self.barLayout)
        self.layout.addWidget(self.__stackedWidget)
        self.setLayout(self.layout)
        
        # initialize the delay timer
        self.__actionMethod = None
        self.__delayTimer = QTimer(self)
        self.__delayTimer.setSingleShot(True)
        self.__delayTimer.setInterval(delay)
        self.__delayTimer.timeout.connect(self.__delayedAction)
        
        self.__minimized = False
        self.__minSize = 0
        self.__maxSize = 0
        self.__bigSize = QSize()
        
        self.splitter = None
        self.splitterSizes = []
        
        self.__hasFocus = False
        # flag storing if this widget or any child has the focus
        self.__autoHide = False
        
        self.__tabBar.installEventFilter(self)
        
        self.__orientation = E5SideBar.North
        if orientation is None:
            orientation = E5SideBar.North
        self.setOrientation(orientation)
        
        self.__tabBar.currentChanged[int].connect(
            self.__stackedWidget.setCurrentIndex)
        e5App().focusChanged[QWidget, QWidget].connect(self.__appFocusChanged)
        self.__autoHideButton.toggled[bool].connect(self.__autoHideToggled)
    
    def setSplitter(self, splitter):
        """
        Public method to set the splitter managing the sidebar.
        
        @param splitter reference to the splitter (QSplitter)
        """
        self.splitter = splitter
        self.splitter.splitterMoved.connect(self.__splitterMoved)
        self.splitter.setChildrenCollapsible(False)
        index = self.splitter.indexOf(self)
        self.splitter.setCollapsible(index, False)
    
    def __splitterMoved(self, pos, index):
        """
        Private slot to react on splitter moves.
        
        @param pos new position of the splitter handle (integer)
        @param index index of the splitter handle (integer)
        """
        if self.splitter:
            self.splitterSizes = self.splitter.sizes()
    
    def __delayedAction(self):
        """
        Private slot to handle the firing of the delay timer.
        """
        if self.__actionMethod is not None:
            self.__actionMethod()
    
    def setDelay(self, delay):
        """
        Public method to set the delay value for the expand/shrink delay in
        milliseconds.
        
        @param delay value for the expand/shrink delay in milliseconds
            (integer)
        """
        self.__delayTimer.setInterval(delay)
    
    def delay(self):
        """
        Public method to get the delay value for the expand/shrink delay in
        milliseconds.
        
        @return value for the expand/shrink delay in milliseconds (integer)
        """
        return self.__delayTimer.interval()
    
    def __cancelDelayTimer(self):
        """
        Private method to cancel the current delay timer.
        """
        self.__delayTimer.stop()
        self.__actionMethod = None
    
    def shrink(self):
        """
        Public method to record a shrink request.
        """
        self.__delayTimer.stop()
        self.__actionMethod = self.__shrinkIt
        self.__delayTimer.start()
   
    def __shrinkIt(self):
        """
        Private method to shrink the sidebar.
        """
        self.__minimized = True
        self.__bigSize = self.size()
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            self.__minSize = self.minimumSizeHint().height()
            self.__maxSize = self.maximumHeight()
        else:
            self.__minSize = self.minimumSizeHint().width()
            self.__maxSize = self.maximumWidth()
        if self.splitter:
            self.splitterSizes = self.splitter.sizes()
        
        self.__stackedWidget.hide()
        
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            self.setFixedHeight(self.__tabBar.minimumSizeHint().height())
        else:
            self.setFixedWidth(self.__tabBar.minimumSizeHint().width())
        
        self.__actionMethod = None
    
    def expand(self):
        """
        Public method to record a expand request.
        """
        self.__delayTimer.stop()
        self.__actionMethod = self.__expandIt
        self.__delayTimer.start()
    
    def __expandIt(self):
        """
        Private method to expand the sidebar.
        """
        self.__minimized = False
        self.__stackedWidget.show()
        self.resize(self.__bigSize)
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            minSize = max(self.__minSize, self.minimumSizeHint().height())
            self.setMinimumHeight(minSize)
            self.setMaximumHeight(self.__maxSize)
        else:
            minSize = max(self.__minSize, self.minimumSizeHint().width())
            self.setMinimumWidth(minSize)
            self.setMaximumWidth(self.__maxSize)
        if self.splitter:
            self.splitter.setSizes(self.splitterSizes)
        
        self.__actionMethod = None
    
    def isMinimized(self):
        """
        Public method to check the minimized state.
        
        @return flag indicating the minimized state (boolean)
        """
        return self.__minimized
    
    def isAutoHiding(self):
        """
        Public method to check, if the auto hide function is active.
        
        @return flag indicating the state of auto hiding (boolean)
        """
        return self.__autoHide
    
    def eventFilter(self, obj, evt):
        """
        Public method to handle some events for the tabbar.
        
        @param obj reference to the object (QObject)
        @param evt reference to the event object (QEvent)
        @return flag indicating, if the event was handled (boolean)
        """
        if obj == self.__tabBar:
            if evt.type() == QEvent.MouseButtonPress:
                pos = evt.pos()
                for i in range(self.__tabBar.count()):
                    if self.__tabBar.tabRect(i).contains(pos):
                        break
                
                if i == self.__tabBar.currentIndex():
                    if self.isMinimized():
                        self.expand()
                    else:
                        self.shrink()
                    return True
                elif self.isMinimized():
                    self.expand()
            elif evt.type() == QEvent.Wheel:
                if qVersion() >= "5.0.0":
                    delta = evt.angleDelta().y()
                else:
                    delta = evt.delta()
                if delta > 0:
                    self.prevTab()
                else:
                    self.nextTab()
                return True
        
        return QWidget.eventFilter(self, obj, evt)
    
    def addTab(self, widget, iconOrLabel, label=None):
        """
        Public method to add a tab to the sidebar.
        
        @param widget reference to the widget to add (QWidget)
        @param iconOrLabel reference to the icon or the label text of the tab
            (QIcon, string)
        @param label the labeltext of the tab (string) (only to be
            used, if the second parameter is a QIcon)
        """
        if label:
            index = self.__tabBar.addTab(iconOrLabel, label)
            self.__tabBar.setTabToolTip(index, label)
        else:
            index = self.__tabBar.addTab(iconOrLabel)
            self.__tabBar.setTabToolTip(index, iconOrLabel)
        self.__stackedWidget.addWidget(widget)
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            self.__minSize = self.minimumSizeHint().height()
        else:
            self.__minSize = self.minimumSizeHint().width()
    
    def insertTab(self, index, widget, iconOrLabel, label=None):
        """
        Public method to insert a tab into the sidebar.
        
        @param index the index to insert the tab at (integer)
        @param widget reference to the widget to insert (QWidget)
        @param iconOrLabel reference to the icon or the labeltext of the tab
            (QIcon, string)
        @param label the labeltext of the tab (string) (only to be
            used, if the second parameter is a QIcon)
        """
        if label:
            index = self.__tabBar.insertTab(index, iconOrLabel, label)
            self.__tabBar.setTabToolTip(index, label)
        else:
            index = self.__tabBar.insertTab(index, iconOrLabel)
            self.__tabBar.setTabToolTip(index, iconOrLabel)
        self.__stackedWidget.insertWidget(index, widget)
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            self.__minSize = self.minimumSizeHint().height()
        else:
            self.__minSize = self.minimumSizeHint().width()
    
    def removeTab(self, index):
        """
        Public method to remove a tab.
        
        @param index the index of the tab to remove (integer)
        """
        self.__stackedWidget.removeWidget(self.__stackedWidget.widget(index))
        self.__tabBar.removeTab(index)
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            self.__minSize = self.minimumSizeHint().height()
        else:
            self.__minSize = self.minimumSizeHint().width()
    
    def clear(self):
        """
        Public method to remove all tabs.
        """
        while self.count() > 0:
            self.removeTab(0)
    
    def prevTab(self):
        """
        Public slot used to show the previous tab.
        """
        ind = self.currentIndex() - 1
        if ind == -1:
            ind = self.count() - 1
            
        self.setCurrentIndex(ind)
        self.currentWidget().setFocus()
    
    def nextTab(self):
        """
        Public slot used to show the next tab.
        """
        ind = self.currentIndex() + 1
        if ind == self.count():
            ind = 0
            
        self.setCurrentIndex(ind)
        self.currentWidget().setFocus()
    
    def count(self):
        """
        Public method to get the number of tabs.
        
        @return number of tabs in the sidebar (integer)
        """
        return self.__tabBar.count()
    
    def currentIndex(self):
        """
        Public method to get the index of the current tab.
        
        @return index of the current tab (integer)
        """
        return self.__stackedWidget.currentIndex()
    
    def setCurrentIndex(self, index):
        """
        Public slot to set the current index.
        
        @param index the index to set as the current index (integer)
        """
        self.__tabBar.setCurrentIndex(index)
        self.__stackedWidget.setCurrentIndex(index)
        if self.isMinimized():
            self.expand()
    
    def currentWidget(self):
        """
        Public method to get a reference to the current widget.
        
        @return reference to the current widget (QWidget)
        """
        return self.__stackedWidget.currentWidget()
    
    def setCurrentWidget(self, widget):
        """
        Public slot to set the current widget.
        
        @param widget reference to the widget to become the current widget
            (QWidget)
        """
        self.__stackedWidget.setCurrentWidget(widget)
        self.__tabBar.setCurrentIndex(self.__stackedWidget.currentIndex())
        if self.isMinimized():
            self.expand()
    
    def indexOf(self, widget):
        """
        Public method to get the index of the given widget.
        
        @param widget reference to the widget to get the index of (QWidget)
        @return index of the given widget (integer)
        """
        return self.__stackedWidget.indexOf(widget)
    
    def isTabEnabled(self, index):
        """
        Public method to check, if a tab is enabled.
        
        @param index index of the tab to check (integer)
        @return flag indicating the enabled state (boolean)
        """
        return self.__tabBar.isTabEnabled(index)
    
    def setTabEnabled(self, index, enabled):
        """
        Public method to set the enabled state of a tab.
        
        @param index index of the tab to set (integer)
        @param enabled enabled state to set (boolean)
        """
        self.__tabBar.setTabEnabled(index, enabled)
    
    def orientation(self):
        """
        Public method to get the orientation of the sidebar.
        
        @return orientation of the sidebar (North, East, South, West)
        """
        return self.__orientation
    
    def setOrientation(self, orient):
        """
        Public method to set the orientation of the sidebar.

        @param orient orientation of the sidebar (North, East, South, West)
        """
        if orient == E5SideBar.North:
            self.__tabBar.setShape(QTabBar.RoundedNorth)
            self.__tabBar.setSizePolicy(
                QSizePolicy.Expanding, QSizePolicy.Preferred)
            self.barLayout.setDirection(QBoxLayout.LeftToRight)
            self.layout.setDirection(QBoxLayout.TopToBottom)
            self.layout.setAlignment(self.barLayout, Qt.AlignLeft)
        elif orient == E5SideBar.East:
            self.__tabBar.setShape(QTabBar.RoundedEast)
            self.__tabBar.setSizePolicy(
                QSizePolicy.Preferred, QSizePolicy.Expanding)
            self.barLayout.setDirection(QBoxLayout.TopToBottom)
            self.layout.setDirection(QBoxLayout.RightToLeft)
            self.layout.setAlignment(self.barLayout, Qt.AlignTop)
        elif orient == E5SideBar.South:
            self.__tabBar.setShape(QTabBar.RoundedSouth)
            self.__tabBar.setSizePolicy(
                QSizePolicy.Expanding, QSizePolicy.Preferred)
            self.barLayout.setDirection(QBoxLayout.LeftToRight)
            self.layout.setDirection(QBoxLayout.BottomToTop)
            self.layout.setAlignment(self.barLayout, Qt.AlignLeft)
        elif orient == E5SideBar.West:
            self.__tabBar.setShape(QTabBar.RoundedWest)
            self.__tabBar.setSizePolicy(
                QSizePolicy.Preferred, QSizePolicy.Expanding)
            self.barLayout.setDirection(QBoxLayout.TopToBottom)
            self.layout.setDirection(QBoxLayout.LeftToRight)
            self.layout.setAlignment(self.barLayout, Qt.AlignTop)
        self.__orientation = orient
    
    def tabIcon(self, index):
        """
        Public method to get the icon of a tab.
        
        @param index index of the tab (integer)
        @return icon of the tab (QIcon)
        """
        return self.__tabBar.tabIcon(index)
    
    def setTabIcon(self, index, icon):
        """
        Public method to set the icon of a tab.
        
        @param index index of the tab (integer)
        @param icon icon to be set (QIcon)
        """
        self.__tabBar.setTabIcon(index, icon)
    
    def tabText(self, index):
        """
        Public method to get the text of a tab.
        
        @param index index of the tab (integer)
        @return text of the tab (string)
        """
        return self.__tabBar.tabText(index)
    
    def setTabText(self, index, text):
        """
        Public method to set the text of a tab.
        
        @param index index of the tab (integer)
        @param text text to set (string)
        """
        self.__tabBar.setTabText(index, text)
    
    def tabToolTip(self, index):
        """
        Public method to get the tooltip text of a tab.
        
        @param index index of the tab (integer)
        @return tooltip text of the tab (string)
        """
        return self.__tabBar.tabToolTip(index)
    
    def setTabToolTip(self, index, tip):
        """
        Public method to set the tooltip text of a tab.
        
        @param index index of the tab (integer)
        @param tip tooltip text to set (string)
        """
        self.__tabBar.setTabToolTip(index, tip)
    
    def tabWhatsThis(self, index):
        """
        Public method to get the WhatsThis text of a tab.
        
        @param index index of the tab (integer)
        @return WhatsThis text of the tab (string)
        """
        return self.__tabBar.tabWhatsThis(index)
    
    def setTabWhatsThis(self, index, text):
        """
        Public method to set the WhatsThis text of a tab.
        
        @param index index of the tab (integer)
        @param text WhatsThis text to set (string)
        """
        self.__tabBar.setTabWhatsThis(index, text)
    
    def widget(self, index):
        """
        Public method to get a reference to the widget associated with a tab.
        
        @param index index of the tab (integer)
        @return reference to the widget (QWidget)
        """
        return self.__stackedWidget.widget(index)
    
    def saveState(self):
        """
        Public method to save the state of the sidebar.
        
        @return saved state as a byte array (QByteArray)
        """
        if len(self.splitterSizes) == 0:
            if self.splitter:
                self.splitterSizes = self.splitter.sizes()
            self.__bigSize = self.size()
            if self.__orientation in [E5SideBar.North, E5SideBar.South]:
                self.__minSize = self.minimumSizeHint().height()
                self.__maxSize = self.maximumHeight()
            else:
                self.__minSize = self.minimumSizeHint().width()
                self.__maxSize = self.maximumWidth()
        
        data = QByteArray()
        stream = QDataStream(data, QIODevice.WriteOnly)
        stream.setVersion(QDataStream.Qt_4_6)
        
        stream.writeUInt16(self.Version)
        stream.writeBool(self.__minimized)
        stream << self.__bigSize
        stream.writeUInt16(self.__minSize)
        stream.writeUInt16(self.__maxSize)
        stream.writeUInt16(len(self.splitterSizes))
        for size in self.splitterSizes:
            stream.writeUInt16(size)
        stream.writeBool(self.__autoHide)
        
        return data
    
    def restoreState(self, state):
        """
        Public method to restore the state of the sidebar.
        
        @param state byte array containing the saved state (QByteArray)
        @return flag indicating success (boolean)
        """
        if state.isEmpty():
            return False
        
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            minSize = self.layout.minimumSize().height()
            maxSize = self.maximumHeight()
        else:
            minSize = self.layout.minimumSize().width()
            maxSize = self.maximumWidth()
        
        data = QByteArray(state)
        stream = QDataStream(data, QIODevice.ReadOnly)
        stream.setVersion(QDataStream.Qt_4_6)
        stream.readUInt16()  # version
        minimized = stream.readBool()
        
        if minimized and not self.__minimized:
            self.shrink()
        
        stream >> self.__bigSize
        self.__minSize = max(stream.readUInt16(), minSize)
        self.__maxSize = max(stream.readUInt16(), maxSize)
        count = stream.readUInt16()
        self.splitterSizes = []
        for i in range(count):
            self.splitterSizes.append(stream.readUInt16())
        
        self.__autoHide = stream.readBool()
        self.__autoHideButton.setChecked(not self.__autoHide)
        
        if not minimized:
            self.expand()
        
        return True
    
    #######################################################################
    ## methods below implement the autohide functionality
    #######################################################################
    
    def __autoHideToggled(self, checked):
        """
        Private slot to handle the toggling of the autohide button.
        
        @param checked flag indicating the checked state of the button
            (boolean)
        """
        self.__autoHide = not checked
        if self.__autoHide:
            self.__autoHideButton.setIcon(
                UI.PixmapCache.getIcon("autoHideOn.png"))
        else:
            self.__autoHideButton.setIcon(
                UI.PixmapCache.getIcon("autoHideOff.png"))
    
    def __appFocusChanged(self, old, now):
        """
        Private slot to handle a change of the focus.
        
        @param old reference to the widget, that lost focus (QWidget or None)
        @param now reference to the widget having the focus (QWidget or None)
        """
        self.__hasFocus = self.isAncestorOf(now)
        if self.__autoHide and not self.__hasFocus and not self.isMinimized():
            self.shrink()
        elif self.__autoHide and self.__hasFocus and self.isMinimized():
            self.expand()
    
    def enterEvent(self, event):
        """
        Protected method to handle the mouse entering this widget.
        
        @param event reference to the event (QEvent)
        """
        if self.__autoHide and self.isMinimized():
            self.expand()
        else:
            self.__cancelDelayTimer()
    
    def leaveEvent(self, event):
        """
        Protected method to handle the mouse leaving this widget.
        
        @param event reference to the event (QEvent)
        """
        if self.__autoHide and not self.__hasFocus and not self.isMinimized():
            self.shrink()
        else:
            self.__cancelDelayTimer()
    
    def shutdown(self):
        """
        Public method to shut down the object.
        
        This method does some preparations so the object can be deleted
        properly. It disconnects from the focusChanged signal in order to
        avoid trouble later on.
        """
        e5App().focusChanged[QWidget, QWidget].disconnect(
            self.__appFocusChanged)
Beispiel #31
0
class CToolBarArea(QWidget):
    signalDragStart = pyqtSignal()
    signalDragEnd = pyqtSignal()
    signalItemDropped = pyqtSignal(CToolBarAreaItem, QWidget, int)

    def __init__(self, parent, orientation):
        super().__init__(parent)
        self.editor = parent
        self.orientation = orientation
        self.dropTargetSpacer = None
        self.actionContextPosition = QPoint()
        self.isLocked = False

        if self.orientation == Qt.Horizontal:
            self.layout_ = QBoxLayout(QBoxLayout.LeftToRight)
        else:
            self.layout_ = QBoxLayout(QBoxLayout.TopToBottom)

        self.layout_.setSpacing(0)
        self.layout_.setContentsMargins(0, 0, 0, 0)

        self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.setLayout(self.layout_)
        self.setAcceptDrops(True)
        self.setContextMenuPolicy(Qt.CustomContextMenu)

        # print ( "CToolBarArea.__init__", parent )

    def getOrientation(self):
        return self.orientation

    def getToolBars(self):
        items = getAllItems(self)
        toolBarItems = []

        for item in items:
            if item.getType() != CToolBarAreaType.ToolBar:
                continue
            toolBarItems.append(item)

        return toolBarItems

    def getLargestItemMinimumSize(self):
        minSize = self.minimumSize()
        items = getAllItems(self)
        for item in items:
            minSize = minSize.expandedTo(item.getMinimumSize())

        return minSize

    def setOrientation(self, orientation):
        self.orientation = orientation
        self.layout_.setDirection(QBoxLayout.LeftToRight if self.orientation ==
                                  Qt.Horizontal else QBoxLayout.TopToBottom)
        self.updateLayoutAlignment()

        items = getAllItems(self)
        for item in items:
            item.setOrientation(self.orientation)

    def setActionContextPosition(self, actionContextPosition):
        self.actionContextPosition = actionContextPosition

    def fillContextMenu(self, menu):
        pass

    def addItem(self, item, targetIndex):
        item.signalDragStart.connect(self.onDragStart)
        item.signalDragEnd.connect(self.onDragEnd)
        item.setOrientation(self.orientation)
        item.setLocked(self.isLocked)
        self.layout_.insertWidget(targetIndex, item)
        item.setArea(self)

    def addToolBar(self, toolBar, targetIndex):
        self.addItem(CToolBarItem(self, toolBar, self.orientation),
                     targetIndex)

    def addSpacer(self, spacerType, targetIndex):
        self.addItem(CSpacerItem(self, spacerType, self.orientation),
                     targetIndex)
        if spacerType == CSpacerType.Expanding:
            self.layout_.setAlignment(0)

    def removeItem(self, item):
        self.layout_.removeWidget(item)
        item.signalDragStart.disconnect(self)
        item.signalDragEnd.disconnect(self)

        self.updateLayoutAlignment(item)

    def deleteToolBar(self, toolBarItem):
        if self.isAncestorOf(toolBarItem):
            qWarning("Trying to remove non-owned toolbar from area")
            return
        toolBarItem.deleteLater()

    def hideAll(self):
        items = getAllItems(self)
        for item in items:
            item.setVisible(False)

    def findToolBarByName(self, szToolBarName):
        toolBarItems = self.findChildren(CToolBarItem, "",
                                         Qt.FindDirectChildrenOnly)
        for toolBarItem in toolBarItems:
            if toolBarItem.getName() == szToolBarName:
                return toolBarItem

        print("Toolbar not found: %s" % szToolBarName)
        return None

    def setLocked(self, isLocked):
        self.isLocked = isLocked
        items = getAllItems(self)
        for item in items:
            item.setLocked(isLocked)

    def getState(self):
        pass

    def setState(self, state):
        pass

    def dragEnterEvent(self, event):
        print("CToolBarArea.dragEnterEvent", event)
        dragDropData = CDragDropData.fromMimeData(event.mimeData())
        if dragDropData.hasCustomData(CToolBarAreaItem.getMimeType()):
            byteArray = dragDropData.getCustomData(
                CToolBarAreaItem.getMimeType())
            stream = QDataStream(byteArray)
            value = None
            stream >> value
            draggedItem = value if isinstance(value,
                                              CToolBarAreaItem) else None

            if not self.parentWidget().isAncestorOf(draggedItem):
                return

            event.acceptProposedAction()

            self.setProperty("dragHover", True)
            self.style().unpolish(self)
            self.style().polish(self)

    def dragMoveEvent(self, event):
        dragDropData = CDragDropData.fromMimeData(event.mimeData())
        if dragDropData.hasCustomData(CToolBarAreaItem.getMimeType()):
            targetIndex = self.getPlacementIndexFromPosition(
                self.mapToGlobal(event.pos()))
            event.acceptProposedAction()

            if self.dropTargetSpacer and targetIndex == self.layout_.indexOf(
                    self.dropTargetSpacer):
                return

            byteArray = dragDropData.getCustomData(
                CToolBarAreaItem.getMimeType())
            stream = QDataStream(byteArray)
            value = None
            stream >> value
            draggedItem = value if isinstance(value,
                                              CToolBarAreaItem) else None

            if not self.parentWidget().isAncestorOf(draggedItem):
                return

            spacerWidth = draggedItem.width()
            spacerHeight = draggedItem.height()

            if draggedItem.getOrientation() != self.orientation:
                tempWidth = spacerWidth
                spacerWidth = spacerHeight
                spacerHeight = tempWidth

            if self.dropTargetSpacer == None:
                self.dropTargetSpacer = QSpacerItem(spacerWidth, spacerHeight,
                                                    QSizePolicy.Fixed,
                                                    QSizePolicy.Fixed)
            else:
                spacerIndex = self.layout_.indexOf(self.dropTargetSpacer)
                if spacerIndex == targetIndex - 1 or (
                        targetIndex == -1
                        and spacerIndex == self.layout_.count() - 1):
                    return

                self.removeDropTargetSpacer()
                self.dropTargetSpacer = QSpacerItem(spacerWidth, spacerHeight,
                                                    QSizePolicy.Fixed,
                                                    QSizePolicy.Fixed)

            self.layout_.insertSpacerItem(targetIndex, self.dropTargetSpacer)

    def dragLeaveEvent(self, event):
        self.removeDropTargetSpacer()

        self.setProperty("dragHover", False)
        self.style().unpolish(self)
        self.style().polish(self)

    def dropEvent(self, event):
        dragDropData = CDragDropData.fromMimeData(event.mimeData())
        if dragDropData.hasCustomData(CToolBarAreaItem.getMimeType()):
            event.acceptProposedAction()
            byteArray = dragDropData.getCustomData(
                CToolBarAreaItem.getMimeType())
            stream = QDataStream(byteArray)
            value = None
            stream >> value
            item = value if isinstance(value, CToolBarAreaItem) else None

            targetIndex = -1

            if self.dropTargetSpacer:
                targetIndex = self.layout_.indexOf(self.dropTargetSpacer)

                containerIndex = self.layout_.indexOf(item)
                if containerIndex >= 0 and containerIndex < targetIndex:
                    targetIndex -= 1

                self.removeDropTargetSpacer()

            if targetIndex >= self.layout_.count():
                targetIndex = -1

            self.signalItemDropped.emit(item, self, targetIndex)

    def customEvent(self, event):
        pass

    def paintEvent(self, event):
        styleOption = QStyleOption()
        styleOption.initFrom(self)
        painter = QPainter(self)
        self.style().drawPrimitive(QStyle.PE_Widget, styleOption, painter,
                                   self)

    def onDragStart(self, item):
        self.updateLayoutAlignment(item)
        item.setVisiable(False)
        self.signalDragStart.emit()

    def onDragEnd(self, item):
        item.setVisiable(True)
        self.signalDragEnd.emit()

    def removeDropTargetSpacer(self):
        if self.dropTargetSpacer:
            self.layout_.removeItem(self.dropTargetSpacer)
            self.dropTargetSpacer = None

    def indexForItem(self, item):
        return self.layout_.indexOf(item)

    def moveItem(self, item, destinationIndex):
        sourceIndex = self.indexForItem(item)
        if sourceIndex == destinationIndex:
            return
        self.layout_.insertWidget(destinationIndex, item)

    def updateLayoutAlignment(self, itemToBeRemoved=None):
        spacers = self.findChildren(CSpacerItem, "", Qt.FindDirectChildrenOnly)
        expandingSpacers = []
        for spacer in spacers:
            if spacer.getSpacerType() == CSpacerType.Expanding:
                expandingSpacers.append(spacer)

        if len(expandingSpacers) == 0 or len(expandingSpacers) != 0 or (
                len(expandingSpacers) == 1
                and expandingSpacers[0] == itemToBeRemoved):
            if self.orientation == Qt.Horizontal:
                self.layout_.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
            else:
                self.layout_.setAlignment(Qt.AlignTop | Qt.AlignHCenter)

    def getItemAtPosition(self, globalPos):
        object = QApplication.widgetAt(globalPos)
        if object == None or object == self:
            return None

        item = object if isinstance(object, CToolBarAreaItem) else None
        while item == None and object.parent():
            object = object.parent()
            item = object if isinstance(object, CToolBarAreaItem) else None

        return item

    def getPlacementIndexFromPosition(self, globalPos):
        targetIndex = -1
        item = self.getItemAtPosition(globalPos)

        if item == None:
            localPos = self.mapFromGlobal(globalPos)
            if self.dropTargetSpacer:
                geom = self.dropTargetSpacer.geometry()
                if geom.contains(localPos):
                    targetIndex = self.layout_.indexOf(self.dropTargetSpacer)

            return targetIndex

        targetIndex = self.indexForItem(item)

        if self.orientation == Qt.Horizontal and item.mapFromGlobal(
                globalPos).x() > item.width() / 2:
            targetIndex += 1
        elif self.orientation == Qt.Vertical and item.mapFromGlobal(
                globalPos).y() > item.height() / 2:
            targetIndex += 1

        if targetIndex >= self.layout_.count():
            targetIndex = -1

        return targetIndex
Beispiel #32
0
class EditorWidget(QWidget):

    # Adding signal
    catCreated = pyqtSignal(Tag)
    catClicked = pyqtSignal(Tag)
    childClicked = pyqtSignal(str)

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

        self.stylesheet_filename = 'GUI/style/nodestyle.qss'
        self.loadStylesheet(self.stylesheet_filename)
        self.aiml = AIML()
        self.responseTable = None

        self.initUI(window)

    def initUI(self, window):
        self.layout = QBoxLayout(QBoxLayout.LeftToRight)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(self.layout)

        # crate graphics scene
        self.scene = Scene()
        self.grScene = self.scene.grScene

        ########## making connections to slots ################
        window.catCreated.connect(
            self.categoryCreated
        )  # connecting signal from Editor Window that is sending created category
        window.catUpdated.connect(
            self.categoryUpdated
        )  # connecting signal from EditorWindow to update Node

        # self.addNodes()
        # self.addDebugContent()
        # create graphics view
        self.view = QDMGraphicsView(self.scene.grScene, self)
        self.layout.addWidget(self.view)

    def addNodes(self):
        node1 = Node(self.scene,
                     "My Awesome Node 1",
                     inputs=[0, 0, 0],
                     outputs=[1])
        node2 = Node(self.scene,
                     "My Awesome Node 2",
                     inputs=[3, 3, 3],
                     outputs=[1])
        node3 = Node(self.scene,
                     "My Awesome Node 3",
                     inputs=[2, 2, 2],
                     outputs=[1])
        node4 = Node(
            self.scene,
            "A Category",
            inputs=[1, 1],
            outputs=[2, 2],
        )
        node1.setPos(-350, -250)
        node2.setPos(-75, 0)
        node3.setPos(200, -150)
        node4.setPos(200, -50)

        edge1 = Edge(self.scene,
                     node1.outputs[0],
                     node2.inputs[0],
                     edge_type=EDGE_TYPE_BEZIER)
        edge2 = Edge(self.scene,
                     node2.outputs[0],
                     node3.inputs[0],
                     edge_type=EDGE_TYPE_BEZIER)

    def addNode(self, title, inputs, outputs, posx, posy):
        node1 = Node(self.scene, title=title, inputs=inputs, outputs=outputs)
        node1.setPos(posx, posy)

    def updateNode(self, cat):
        try:
            print("updating node in display")
            for node in self.scene.nodes:
                if node.category.id == cat.id:
                    print("found node to update")
                    node.category = cat
                    print(str(node.category))
                    node.content.wdg_label.clear()
                    node.content.wdg_label.displayVisuals(cat)
                    return node
        except Exception as ex:
            print(ex)

    def addDebugContent(self):
        greenBrush = QBrush(Qt.green)
        outlinePen = QPen(Qt.black)
        outlinePen.setWidth(2)

        rect = self.grScene.addRect(-100, -100, 80, 100, outlinePen,
                                    greenBrush)
        rect.setFlag(QGraphicsItem.ItemIsMovable)

        text = self.grScene.addText("This is my Awesome text!",
                                    QFont("Ubuntu"))
        text.setFlag(QGraphicsItem.ItemIsSelectable)
        text.setFlag(QGraphicsItem.ItemIsMovable)
        text.setDefaultTextColor(QColor.fromRgbF(1.0, 1.0, 1.0))

        widget1 = QPushButton("Hello World")
        proxy1 = self.grScene.addWidget(widget1)
        proxy1.setFlag(QGraphicsItem.ItemIsMovable)
        proxy1.setPos(0, 30)

        widget2 = QTextEdit()
        proxy2 = self.grScene.addWidget(widget2)
        proxy2.setFlag(QGraphicsItem.ItemIsSelectable)
        proxy2.setPos(0, 60)

        line = self.grScene.addLine(-200, -200, 400, -100, outlinePen)
        line.setFlag(QGraphicsItem.ItemIsMovable)
        line.setFlag(QGraphicsItem.ItemIsSelectable)

    def loadStylesheet(self, filename):
        print('STYLE loading:', filename)
        file = QFile(filename)
        file.open(QFile.ReadOnly | QFile.Text)
        stylesheet = file.readAll()
        QApplication.instance().setStyleSheet(str(stylesheet,
                                                  encoding='utf-8'))

    """
    Determine if the condition or random table has text afterwards
    """

    def tableContainsTail(self, template):
        try:
            index = 0
            for tag in template.tags:
                print("Beginning of for loop")
                if isinstance(tag, str) is True and tag is not " ":
                    print("found string")
                    continue
                elif tag.type == "condition" or tag.type == "random":
                    # Check to see if we are at end of array
                    if index == len(template.tags) - 1:
                        return False

                    print("next item in tags list: " +
                          str(template.tags[index + 1]))
                    if isinstance(template.tags[index + 1], str) is True:
                        print("returning true")
                        return True
                    else:
                        print("returning false")
                        return False
                index = index + 1
        except Exception as ex:
            print("Exception caught in tableContainsTail!")
            print(ex)
            handleError(ex)

    """
    Function to find the sentence to be used for <that> tag of potential children
    """

    def getLastSentence(self, cat):
        try:
            template = cat.findTag("template")
            sentences = []
            if template is None:
                print("Template is empty")
                return
            condition = template.findTag("condition")
            random = template.findTag("random")
            print("Before logic")
            if condition is None and random is None:
                print("no random or condition tag found in template")
                print(str(template))
                tempString = template.findTag("text")
                print(tempString)
                tempArr = tempString.split()
                index = 0
                for word in reversed(tempArr):
                    if "." in word or "?" in word or "!" in word:
                        if index == 0:
                            print(
                                "Found last punctuation mark on very first word. Keep searching."
                            )
                            print(word)
                        else:
                            print("Found the start of the last sentence")
                            print(word)
                            arrSize = len(tempArr)
                            start = arrSize - (index)
                            lastSentence = tempArr[start:arrSize]
                            lastSentence = " ".join(lastSentence)
                            print(lastSentence)
                            sentences.append(lastSentence)
                    index = index + 1

                # If made it to end of array without finding another punctiation mark. return full text in template
                sentences.append(tempString)
                return sentences
            else:
                print("template contains either a random or condition tag")
                print(str(template))
                if self.tableContainsTail(template) is True:
                    print("Random or Condition tag has text after")
                    tempString = template.findTag("text", 2)
                    print(tempString)
                    tempArr = tempString.split()
                    index = 0
                    for word in reversed(tempArr):
                        if "." in word or "?" in word or "!" in word:
                            if index == 0:
                                print(
                                    "Found last punctuation mark on very first word. Keep searching."
                                )
                                print(word)
                            else:
                                print("Found the start of the last sentence")
                                print(word)
                                arrSize = len(tempArr)
                                start = arrSize - (index)
                                lastSentence = tempArr[start:arrSize]
                                lastSentence = " ".join(lastSentence)
                                print(lastSentence)
                                sentences.append(lastSentence)
                        index = index + 1
                    # If made it to end of array without finding another punctiation mark. return full text in template
                    sentences.append(tempString)
                    return sentences
                else:
                    print(
                        "Random or Condition tag is the last thing in the template"
                    )
                    if condition is not None:
                        print("table contains condition table")
                        for li in condition.tags:
                            liText = li.findTag("text")
                            print("text inside condition: " + liText)
                            liArr = liText.split()
                            index = 0
                            punctuationExists = False
                            for word in reversed(liArr):
                                if "." in word or "?" in word or "!" in word:
                                    if index == 0:
                                        print(
                                            "Found last punctuation mark on very first word. Keep searching."
                                        )
                                        print(word)
                                    else:
                                        print(
                                            "Found the start of the last sentence"
                                        )
                                        print(word)
                                        arrSize = len(liArr)
                                        start = arrSize - (index)
                                        lastSentence = liArr[start:arrSize]
                                        lastSentence = " ".join(lastSentence)
                                        print(lastSentence)
                                        sentences.append(lastSentence)
                                        punctuationExists = True
                                        break
                                index = index + 1
                            # If made it to end of array without finding another punctiation mark. return full text in tag
                            if punctuationExists is False:
                                sentences.append(liText)
                        return sentences
                        print("done goofed")
                    else:
                        print("table contains random table")
                        for li in random.tags:
                            liText = li.findTag("text")
                            print("text inside random: " + liText)
                            liArr = liText.split()
                            index = 0
                            punctuationExists = False
                            for word in reversed(liArr):
                                if "." in word or "?" in word or "!" in word:
                                    if index == 0:
                                        print(
                                            "Found last punctuation mark on very first word. Keep searching."
                                        )
                                        print(word)
                                    else:
                                        print(
                                            "Found the start of the last sentence"
                                        )
                                        print(word)
                                        arrSize = len(liArr)
                                        start = arrSize - (index)
                                        lastSentence = liArr[start:arrSize]
                                        lastSentence = " ".join(lastSentence)
                                        print(lastSentence)
                                        sentences.append(lastSentence)
                                        punctuationExists = True
                                        break
                                index = index + 1
                            # If made it to end of array without finding another punctiation mark. return full text in tag
                            if punctuationExists is False:
                                sentences.append(liText)
                        return sentences
                        print("done goofed")
        except Exception as ex:
            print("Exception caught in getLastSentence")
            print(ex)
            handleError(ex)

    """
    Find child nodes in the scene and add edges based off of <that> tags
    """

    def findChildNodes(self, newnode, thatStr):
        try:
            print("looking for child nodes")
            xOffset = 0
            for node in self.scene.nodes:
                thatTag = node.category.findTag("that")
                print(str(thatTag))
                if thatTag is None:
                    print("no that tag found in category: " +
                          str(node.category))
                elif newnode == node:
                    print("looking at node just created. Do nothing")
                else:
                    # That tag was found, add an edge
                    print("that tag was found in category: " +
                          str(node.category))
                    thatText = thatTag.findTag("text")
                    if thatText.lower() == thatStr.lower():
                        print("found child!")
                        parentsocket = Socket(newnode,
                                              position=RIGHT_BOTTOM,
                                              socket_type=2)
                        newnode.inputs.append(
                            parentsocket)  # outputs is children

                        if node not in newnode.children:
                            newnode.children.append(node)

                        childsocket = Socket(node)
                        node.outputs.append(childsocket)

                        if newnode not in node.parents:
                            node.parents.append(newnode)

                        edge = Edge(self.scene, parentsocket, childsocket)
                    else:
                        print("Not a match for a child")
        except Exception as ex:
            print(
                "Exception caught in EditorWidget when looking for child nodes"
            )
            print(ex)
            handleError(ex)

    """
    Find parent nodes in the scene and add edges based off of <that> tags
    """

    def findParentNodes(self, newnode):
        try:
            print("looking for parent nodes")
            mythatTag = newnode.category.findTag("that")
            if mythatTag is None:
                print("no that tag so node will not have any parents")
                return
            thatText = mythatTag.findTag("text")
            print("Text of That Tag to look for: " + thatText)
            xOffset = 0
            for node in self.scene.nodes:
                if node == newnode:
                    print("looking at node just created, do nothing")
                else:
                    print("looking at node with category: " +
                          str(node.category))
                    # template = node.category.findTag("template")
                    templateText = self.getLastSentence(node.category)
                    for text in templateText:
                        if thatText.lower() == text.lower():
                            print("Found parent node!")
                            parentsocket = Socket(node,
                                                  position=RIGHT_BOTTOM,
                                                  socket_type=2)
                            node.inputs.append(parentsocket)

                            # need to check if node exists in list before appending
                            if newnode not in node.children:
                                node.children.append(newnode)

                            childsocket = Socket(newnode)
                            newnode.outputs.append(childsocket)

                            if node not in newnode.parents:
                                newnode.parents.append(node)

                            edge = Edge(self.scene, parentsocket, childsocket)
                        else:
                            print("Not a match for a parent")
        except Exception as ex:
            print(ex)
            handleError(ex)

    """
    Function to organize nodes based on parents and children
    """

    def placeNodes(self, nodes, depth=0):
        # TODO: Recursively look through children. place parents on left, children on the right.
        try:
            print("placing nodes")
            if depth > 5:
                print("reached max depth")
                return

            xOffset = 500
            for node in nodes:
                yOffset = 0
                if node.parents is None:
                    print("node has no parents place to the left.")
                    node.setPos(-900, -900 + yOffset)
                    yOffset = yOffset + 300
                else:
                    print("node has parents")
                    for child in node.children:
                        depth = depth + 1
                        y = node.grNode.y()
                        child.setPos(xOffset, y + yOffset)
                        xOffset = xOffset + 100
                        yOffset = yOffset + 575
                        self.placeNodes(child.children, depth)
                    xOffset = xOffset + 300
        except Exception as ex:
            print("Exception caught placing nodes!")
            print(ex)
            handleError(ex)

    # slot function for a category being created and displaying on editSpace
    @pyqtSlot(Tag)
    def categoryCreated(self, cat):
        try:
            print("slot in EditorWidget, categoryCreated")
            # print(str(cat))
            # print("category id: " + str(cat.id))
            self.aiml.append(cat)
            thatToCheck = self.getLastSentence(cat)
            print("got last sentence of category")
            title = "Category: " + cat.id
            aNode = Node(self.scene, title, cat)
            print("created node")
            aNode.content.wdg_label.displayVisuals(cat)
            print("displayed contents on node")

            for that in thatToCheck:
                self.findChildNodes(aNode, that)
            self.findParentNodes(aNode)

            self.placeNodes(self.scene.nodes)

            for node in self.scene.nodes:
                node.updateConnectedEdges()

            aNode.content.catClicked.connect(
                self.categoryClicked
            )  # connecting signals coming from Content Widget
            print("trying to connect addChild button")
            aNode.content.childClicked.connect(
                self.addChildClicked
            )  # connecting signals coming from Content Widget
        except Exception as ex:
            print("Exception caught in EditorWidget when creating category!")
            print(ex)
            handleError(ex)

    @pyqtSlot(Tag)
    def addChildClicked(self, cat):
        try:
            print("In slot of editor widget")
            template = cat.findTag("template")
            print("template tags list: " + str(template.tags))
            if template.findTag("condition") is None and template.findTag(
                    "random") is None:
                print("no table inside template")
                thatStr = self.getLastSentence(cat)
                print(thatStr)
                self.childClicked.emit(thatStr[0])  # emitting to Editor Window
            else:
                if self.tableContainsTail(template) is False:
                    print(
                        "table is last thing in template. Must choose response to use for that"
                    )
                    template = cat.findTag("template")
                    condition = template.findTag("condition")
                    random = template.findTag("random")
                    if condition is not None:
                        print("create response table out of condition items")
                        self.responseTable = ResponseSelection(tag=condition,
                                                               category=cat,
                                                               editspace=self)
                    else:
                        print("create response table out of random items")
                        self.responseTable = ResponseSelection(tag=random,
                                                               category=cat,
                                                               editspace=self)
                else:
                    print(
                        "table contains tail, there is only one possible sentence to use for that"
                    )
                    thatStr = self.getLastSentence(cat)
                    print(thatStr[0])
                    self.childClicked.emit(
                        thatStr[0])  # emitting to Editor Window
        except Exception as ex:
            print(ex)
            handleError(ex)

    @pyqtSlot(Tag)
    def categoryUpdated(self, cat):
        print("slot in EditorWidget")
        try:
            updatedCat = self.aiml.update(cat)
            updatedNode = self.updateNode(cat)
            thatStr = self.getLastSentence(cat)
            self.findParentNodes(updatedNode)
            that = cat.findTag("that")
            if that is not None:
                self.findChildNodes(updatedNode, thatStr)
            print("display updated")
            print("updated category")
            print(str(updatedCat))
        except Exception as ex:
            print("Exception caught trying to update Node in EditorWidget")
            print(ex)

    @pyqtSlot(Tag)
    def categoryClicked(self, cat):
        print("slot in EditorWidget")
        cat = self.aiml.find(cat.id)
        print(cat)
        self.catClicked.emit(cat)  # emitting signal to be sent to EditorWindow