Beispiel #1
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 #2
0
class AspectRatioWidget(QWidget):
    '''Widget that keeps the aspect ratio of child widget on resize'''
    def __init__(self, widget, aspectRatio):
        super(AspectRatioWidget, self).__init__()
        self.layout = QBoxLayout(QBoxLayout.LeftToRight, self)
        self.layout.addItem(QSpacerItem(0, 0))
        self.layout.addWidget(widget)
        self.layout.addItem(QSpacerItem(0, 0))
        self.setAspectRatio(aspectRatio)

    def setAspectRatio(self, aspectRatio):
        self.aspectRatio = aspectRatio
        self.updateAspectRatio()

    def updateAspectRatio(self):
        newAspectRatio = self.size().width() / self.size().height()
        if newAspectRatio > self.aspectRatio:
            # Too wide
            self.layout.setDirection(QBoxLayout.LeftToRight)
            widgetStretch = self.height() * self.aspectRatio
            outerStretch = (self.width() - widgetStretch) / 2 + 0.5
        else:
            # Too tall
            self.layout.setDirection(QBoxLayout.TopToBottom)
            widgetStretch = self.width() * (1 / self.aspectRatio)
            outerStretch = (self.height() - widgetStretch) / 2 + 0.5

        self.layout.setStretch(0, outerStretch)
        self.layout.setStretch(1, widgetStretch)
        self.layout.setStretch(2, outerStretch)

    def resizeEvent(self, event):
        self.updateAspectRatio()
Beispiel #3
0
class HV(QWidget):
    def __init__(self, labels):
        QWidget.__init__(self)
        self.labels = labels
        self.layout = QBoxLayout(QBoxLayout.LeftToRight)
        for label in labels.labels:
            self.layout.addWidget(label)
        self.setLayout(self.layout)

    def setLabels(self, labels):
        for label in self.labels.labels:
            self.layout.removeWidget(label)
            label.setParent(None)
        self.labels = labels
        for label in labels.labels:
            self.layout.addWidget(label)

    def setLeftToRight(self):
        self.layout.setDirection(QtWidgets.QBoxLayout.LeftToRight)

    def setTopToBottom(self):
        self.layout.setDirection(QtWidgets.QBoxLayout.TopToBottom)
Beispiel #4
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 #5
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 #6
0
class toolbar(QDockWidget):
    """
    Defines the right side toolbar, using QDockWidget. 
    """
    toolbuttonClicked = pyqtSignal(dict)  #signal for any object button pressed

    def __init__(self, parent=None):
        super(toolbar, self).__init__(parent)
        self.toolbarButtonDict = dict(
        )  #initializes empty dict to store toolbar buttons
        self.toolbarLabelDict = dict()
        self.toolbarItems(toolbarItems.keys())  #creates all necessary buttons

        self.setFeatures(QDockWidget.DockWidgetFloatable
                         | QDockWidget.DockWidgetMovable)
        #mainly used to disable closeability of QDockWidget
        self.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea
                             | Qt.NoDockWidgetArea)
        #declare main widget and layout
        self.widget = QWidget(self)
        self.widget.setObjectName("ToolbarWidget")
        self.layout = QBoxLayout(QBoxLayout.TopToBottom, self.widget)
        self.setWindowFlags(Qt.FramelessWindowHint)

        self.searchBox = QLineEdit(
            self.widget)  #search box to search through componenets

        #connect signal to filter slot, add searchbar to toolbar
        self.searchBox.textChanged.connect(self.searchQuery)
        self.layout.addWidget(self.searchBox, alignment=Qt.AlignHCenter)

        #create a scrollable area to house all buttons
        self.diagArea = QScrollArea(self)
        self.diagArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.diagArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.diagArea.setWidgetResizable(True)
        self.layout.addWidget(self.diagArea, stretch=1)
        self.diagAreaWidget = QWidget(
            self.diagArea)  #inner widget for scroll area
        self.diagAreaWidget.setObjectName("ToolbarScrollWidget")
        #custom layout for inner widget
        self.diagAreaLayout = flowLayout(self.diagAreaWidget)
        self.diagAreaLayout.setSizeConstraint(flowLayout.SetMinimumSize)
        self.setWidget(self.widget)  #set main widget to dockwidget

    def clearLayout(self):
        # used to clear all items from toolbar, by parenting it to the toolbar instead
        # this works because changing parents moves widgets to be the child of the new
        # parent, setting it to none, would have qt delete them to free memory
        for i in reversed(range(self.diagAreaLayout.count())):
            # since changing parent would effect indexing, its important to go in reverse
            self.diagAreaLayout.itemAt(i).widget().setParent(self)

    def populateToolbar(self, filterFunc=None):
        #called everytime the button box needs to be updated(incase of a filter)
        self.clearLayout()  #clears layout
        for itemClass in self.toolbarButtonDict.keys():
            self.diagAreaLayout.addWidget(self.toolbarLabelDict[itemClass])
            for item in filter(filterFunc,
                               self.toolbarButtonDict[itemClass].keys()):
                self.diagAreaLayout.addWidget(
                    self.toolbarButtonDict[itemClass][item])
        self.resize()

    def searchQuery(self):
        # shorten toolbaritems list with search items
        # self.populateToolbar() # populate with toolbar items
        text = self.searchBox.text()  #get text
        if text == '':
            self.populateToolbar()  # restore everything on empty string
        else:
            # use regex to search filter through button list and add the remainder to toolbar
            self.populateToolbar(lambda x: search(text, x, IGNORECASE))

    def resize(self):
        # called when main window resizes, overloading resizeEvent caused issues.
        parent = self.parentWidget()  #used to get parent dimensions
        self.layout.setDirection(
            QBoxLayout.TopToBottom
        )  # here so that a horizontal toolbar can be implemented later
        # self.setFixedHeight(self.height()) #span available height
        self.searchBox.setMinimumWidth(.18 * parent.width())
        width = self.width()
        scrollBar = self.diagArea.verticalScrollBar()
        height = self.diagAreaLayout.heightForWidth(width)
        if scrollBar.isVisible():
            width -= app.app.style().pixelMetric(QStyle.PM_ScrollBarExtent)

        # the following line, sets the required height for the current width, so that blank space doesnt occur
        self.diagAreaWidget.setMinimumHeight(height)
        self.setMinimumWidth(.2 * parent.width())  #12% of parent width
        # self.setMinimumWidth(self.diagAreaLayout.minimumSize().width()) #12% of parent width
        self.diagAreaWidget.setLayout(self.diagAreaLayout)
        self.diagArea.setWidget(self.diagAreaWidget)

        for _, label in self.toolbarLabelDict.items():
            label.setFixedWidth(width)

    def resizeEvent(self, event):
        self.resize()

    def toolbarItems(self, itemClasses):
        #helper functions to create required buttons
        for itemClass in itemClasses:
            self.toolbarButtonDict[itemClass] = {}
            label = SectionLabel(itemClass)
            self.toolbarLabelDict[itemClass] = label
            for item in toolbarItems[itemClass].keys():
                obj = toolbarItems[itemClass][item]
                button = toolbarButton(self, obj)
                button.clicked.connect(
                    lambda: self.toolbuttonClicked.emit(obj))
                self.toolbarButtonDict[itemClass][item] = button

    @property
    def toolbarItemList(self):
        #generator to iterate over all buttons
        for i in self.toolbarButtonDict.keys():
            yield i
Beispiel #7
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 #8
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 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)
class QFilterChain(QFilterConfig):
    contentsModified = pyqtSignal()

    def createNewFilterInstance(self):
        return FilterChain()

    def _createControls(self, *args, **kwargs):
        self.setWindowTitle("Configure Filter Chain")
        self.sourceWidget = QWidget(self)
        self.sourceSelection = self.createSourceControl(self.sourceWidget)
        self.sourceSelection.currentDataChanged.connect(self.setFilterSource)

        srclayout = QHBoxLayout()
        srclayout.addWidget(QLabel("Source: ", self.sourceWidget))
        srclayout.addWidget(self.sourceSelection)

        self.sourceWidget.setLayout(srclayout)

        self.availableFilters = QAvailableFilters(self)
        self.availableFilters.setAvailableFilters(filters.values())
        self.availableFilters.setMaximumWidth(240)

        self.currentFilters = QCurrentFilters(self)
        self.currentFilters.setMaximumWidth(240)
        self.currentFilters.listView.contentsModified.connect(self.isModified)

        self.vFilterEdit = VFilterEdit(self)
        self.vFilterEdit.contentsModified.connect(
            self.currentFilters.listView.viewport().update)
        self.vFilterEdit.contentsModified.connect(self.isModified)

        self.vFilterEdit.hide()

        layout = QVBoxLayout()
        self.setLayout(layout)
        layout.addWidget(self.sourceWidget)

        hlayout = QHBoxLayout()
        layout.addLayout(hlayout)

        self.filterlistlayout = QBoxLayout(QBoxLayout.LeftToRight)
        hlayout.addLayout(self.filterlistlayout)

        self.filterlistlayout.addWidget(self.availableFilters)
        self.filterlistlayout.addWidget(self.currentFilters)

        hlayout.addWidget(self.vFilterEdit)

        self._prepareDlgButtons()
        self.setVideoMode(False)

    def setVideoMode(self, flag):
        self.vFilterEdit.setVisible(bool(flag))

        try:
            self.currentFilters.listView.filterMoved.disconnect()

        except Exception:
            pass

        try:
            self.currentFilters.listView.filterRemoved.disconnect()

        except Exception:
            pass

        try:
            self.currentFilters.listView.filterInserted.disconnect()

        except Exception:
            pass

        if flag:
            self.currentFilters.listView.filterMoved.connect(
                self.vFilterEdit.frameTable.handleFilterMoved)
            self.currentFilters.listView.filterRemoved.connect(
                self.vFilterEdit.frameTable.handleFilterRemoved)
            self.currentFilters.listView.filterInserted.connect(
                self.vFilterEdit.frameTable.handleFilterInserted)

            self.filterlistlayout.setDirection(QBoxLayout.TopToBottom)

        else:
            self.filterlistlayout.setDirection(QBoxLayout.LeftToRight)

    def _resetControls(self):
        self.currentFilters.listView.setFilters(self.filtercopy)

        if self.filtercopy.type == "video":
            self.vFilterEdit.setFilters(self.filtercopy)

        self.setVideoMode(self.filtercopy.type == "video")