Exemple #1
0
    def set_corner_text(self, table, text):
        """Set table corner text."""
        # As this is an ugly hack, do everything in
        # try - except blocks, as it may stop working in newer Qt.

        if not hasattr(table, "btn") and not hasattr(table, "btnfailed"):
            try:
                btn = table.findChild(QAbstractButton)

                class efc(QObject):
                    def eventFilter(self, o, e):
                        if (isinstance(o, QAbstractButton) and
                                e.type() == QEvent.Paint):
                            # paint by hand (borrowed from QTableCornerButton)
                            btn = o
                            opt = QStyleOptionHeader()
                            opt.initFrom(btn)
                            state = QStyle.State_None
                            if btn.isEnabled():
                                state |= QStyle.State_Enabled
                            if btn.isActiveWindow():
                                state |= QStyle.State_Active
                            if btn.isDown():
                                state |= QStyle.State_Sunken
                            opt.state = state
                            opt.rect = btn.rect()
                            opt.text = btn.text()
                            opt.position = QStyleOptionHeader.OnlyOneSection
                            painter = QStylePainter(btn)
                            painter.drawControl(QStyle.CE_Header, opt)
                            return True     # eat event
                        return False
                table.efc = efc()
                # disconnect default handler for clicks and connect a new one, which supports
                # both selection and deselection of all data
                btn.clicked.disconnect()
                btn.installEventFilter(table.efc)
                btn.clicked.connect(self._on_select_all)
                table.btn = btn

                if sys.platform == "darwin":
                    btn.setAttribute(Qt.WA_MacSmallSize)

            except Exception:
                table.btnfailed = True

        if hasattr(table, "btn"):
            try:
                btn = table.btn
                btn.setText(text)
                opt = QStyleOptionHeader()
                opt.text = btn.text()
                s = btn.style().sizeFromContents(
                    QStyle.CT_HeaderSection,
                    opt, QSize(),
                    btn).expandedTo(QApplication.globalStrut())
                if s.isValid():
                    table.verticalHeader().setMinimumWidth(s.width())
            except Exception:
                pass
Exemple #2
0
    def set_corner_text(self, table, text):
        """Set table corner text."""
        # As this is an ugly hack, do everything in
        # try - except blocks, as it may stop working in newer Qt.
        # pylint: disable=broad-except
        if not hasattr(table, "btn") and not hasattr(table, "btnfailed"):
            try:
                btn = table.findChild(QAbstractButton)

                class Efc(QObject):
                    @staticmethod
                    def eventFilter(o, e):
                        if (isinstance(o, QAbstractButton)
                                and e.type() == QEvent.Paint):
                            # paint by hand (borrowed from QTableCornerButton)
                            btn = o
                            opt = QStyleOptionHeader()
                            opt.initFrom(btn)
                            state = QStyle.State_None
                            if btn.isEnabled():
                                state |= QStyle.State_Enabled
                            if btn.isActiveWindow():
                                state |= QStyle.State_Active
                            if btn.isDown():
                                state |= QStyle.State_Sunken
                            opt.state = state
                            opt.rect = btn.rect()
                            opt.text = btn.text()
                            opt.position = QStyleOptionHeader.OnlyOneSection
                            painter = QStylePainter(btn)
                            painter.drawControl(QStyle.CE_Header, opt)
                            return True  # eat event
                        return False

                table.efc = Efc()
                # disconnect default handler for clicks and connect a new one, which supports
                # both selection and deselection of all data
                btn.clicked.disconnect()
                btn.installEventFilter(table.efc)
                btn.clicked.connect(self._on_select_all)
                table.btn = btn

                if sys.platform == "darwin":
                    btn.setAttribute(Qt.WA_MacSmallSize)

            except Exception:
                table.btnfailed = True

        if hasattr(table, "btn"):
            try:
                btn = table.btn
                btn.setText(text)
                opt = QStyleOptionHeader()
                opt.text = btn.text()
                s = btn.style().sizeFromContents(QStyle.CT_HeaderSection, opt,
                                                 QSize(), btn)
                if s.isValid():
                    table.verticalHeader().setMinimumWidth(s.width())
            except Exception:
                pass
Exemple #3
0
    def paintSection(self, painter, rect, logicalIndex):
        # type: (QPainter, QRect, int) -> None
        """
        Reimplemented from `QHeaderView`.
        """
        # What follows is similar to QHeaderView::paintSection@Qt 6.0
        if not rect.isValid():
            return  # pragma: no cover
        oldBO = painter.brushOrigin()

        opt = QStyleOptionHeader()
        opt.rect = rect
        self.initStyleOption(opt)

        oBrushButton = opt.palette.brush(QPalette.Button)
        oBrushWindow = opt.palette.brush(QPalette.Window)

        self.initStyleOptionForIndex(opt, logicalIndex)
        opt.rect = rect

        nBrushButton = opt.palette.brush(QPalette.Button)
        nBrushWindow = opt.palette.brush(QPalette.Window)

        if oBrushButton != nBrushButton or oBrushWindow != nBrushWindow:
            painter.setBrushOrigin(opt.rect.topLeft())
        # draw the section
        self.style().drawControl(QStyle.CE_Header, opt, painter, self)

        painter.setBrushOrigin(oldBO)
    def set_corner_text(self, table, text):
        """Set table corner text."""
        # As this is an ugly hack, do everything in
        # try - except blocks, as it may stop working in newer Qt.

        if not hasattr(table, "btn") and not hasattr(table, "btnfailed"):
            try:
                btn = table.findChild(QAbstractButton)

                class efc(QObject):
                    def eventFilter(self, o, e):
                        if isinstance(
                                o,
                                QAbstractButton) and e.type() == QEvent.Paint:
                            # paint by hand (borrowed from QTableCornerButton)
                            btn = o
                            opt = QStyleOptionHeader()
                            opt.initFrom(btn)
                            state = QStyle.State_None
                            if btn.isEnabled():
                                state |= QStyle.State_Enabled
                            if btn.isActiveWindow():
                                state |= QStyle.State_Active
                            if btn.isDown():
                                state |= QStyle.State_Sunken
                            opt.state = state
                            opt.rect = btn.rect()
                            opt.text = btn.text()
                            opt.position = QStyleOptionHeader.OnlyOneSection
                            painter = QStylePainter(btn)
                            painter.drawControl(QStyle.CE_Header, opt)
                            return True  # eat event
                        return False

                table.efc = efc()
                btn.installEventFilter(table.efc)
                table.btn = btn

                if sys.platform == "darwin":
                    btn.setAttribute(Qt.WA_MacSmallSize)

            except Exception:
                table.btnfailed = True

        if hasattr(table, "btn"):
            try:
                btn = table.btn
                btn.setText(text)
                opt = QStyleOptionHeader()
                opt.text = btn.text()
                s = (btn.style().sizeFromContents(
                    QStyle.CT_HeaderSection, opt, QSize(),
                    btn).expandedTo(QApplication.globalStrut()))
                if s.isValid():
                    table.verticalHeader().setMinimumWidth(s.width())
            except Exception:
                pass
    def test_header_view_clickable(self):
        model = QStandardItemModel()
        model.setColumnCount(3)
        header = HeaderView(Qt.Horizontal)
        header.setModel(model)
        header.setSectionsClickable(True)
        header.adjustSize()
        pos = header.sectionViewportPosition(0)
        size = header.sectionSize(0)
        # center of first section
        point = QPoint(pos + size // 2, header.viewport().height() / 2)
        QTest.mousePress(header.viewport(), Qt.LeftButton, Qt.NoModifier, point)

        opt = QStyleOptionHeader()
        header.initStyleOptionForIndex(opt, 0)
        self.assertTrue(opt.state & QStyle.State_Sunken)

        QTest.mouseRelease(header.viewport(), Qt.LeftButton, Qt.NoModifier, point)
        opt = QStyleOptionHeader()
        header.initStyleOptionForIndex(opt, 0)
        self.assertFalse(opt.state & QStyle.State_Sunken)
Exemple #6
0
 def eventFilter(o, e):
     if (isinstance(o, QAbstractButton) and
             e.type() == QEvent.Paint):
         # paint by hand (borrowed from QTableCornerButton)
         btn = o
         opt = QStyleOptionHeader()
         opt.initFrom(btn)
         state = QStyle.State_None
         if btn.isEnabled():
             state |= QStyle.State_Enabled
         if btn.isActiveWindow():
             state |= QStyle.State_Active
         if btn.isDown():
             state |= QStyle.State_Sunken
         opt.state = state
         opt.rect = btn.rect()
         opt.text = btn.text()
         opt.position = QStyleOptionHeader.OnlyOneSection
         painter = QStylePainter(btn)
         painter.drawControl(QStyle.CE_Header, opt)
         return True     # eat event
     return False
Exemple #7
0
 def eventFilter(self, o, e):
     if (isinstance(o, QAbstractButton) and
             e.type() == QEvent.Paint):
         # paint by hand (borrowed from QTableCornerButton)
         btn = o
         opt = QStyleOptionHeader()
         opt.initFrom(btn)
         state = QStyle.State_None
         if btn.isEnabled():
             state |= QStyle.State_Enabled
         if btn.isActiveWindow():
             state |= QStyle.State_Active
         if btn.isDown():
             state |= QStyle.State_Sunken
         opt.state = state
         opt.rect = btn.rect()
         opt.text = btn.text()
         opt.position = QStyleOptionHeader.OnlyOneSection
         painter = QStylePainter(btn)
         painter.drawControl(QStyle.CE_Header, opt)
         return True     # eat event
     return False
Exemple #8
0
    def initStyleOptionForIndex(self, option: QStyleOptionHeader,
                                logicalIndex: int) -> None:
        """
        Similar to initStyleOptionForIndex in Qt 6.0 with the difference that
        `isSectionSelected` is not used, only `sectionIntersectsSelection`
        is used (isSectionSelected will scan the entire model column/row
        when the whole column/row is selected).
        """
        hover = self.logicalIndexAt(self.mapFromGlobal(QCursor.pos()))
        pressed = self.__pressed

        if self.highlightSections():
            is_selected = self.__sectionIntersectsSelection
        else:
            is_selected = lambda _: False

        state = QStyle.State_None
        if self.isEnabled():
            state |= QStyle.State_Enabled
        if self.window().isActiveWindow():
            state |= QStyle.State_Active
        if self.sectionsClickable():
            if logicalIndex == hover:
                state |= QStyle.State_MouseOver
            if logicalIndex == pressed:
                state |= QStyle.State_Sunken
        if self.highlightSections():
            if is_selected(logicalIndex):
                state |= QStyle.State_On
        if self.isSortIndicatorShown() and \
                self.sortIndicatorSection() == logicalIndex:
            option.sortIndicator = (
                QStyleOptionHeader.SortDown if self.sortIndicatorOrder()
                == Qt.AscendingOrder else QStyleOptionHeader.SortUp)

        style = self.style()
        model = self.model()
        orientation = self.orientation()
        textAlignment = model.headerData(logicalIndex, self.orientation(),
                                         Qt.TextAlignmentRole)
        defaultAlignment = self.defaultAlignment()
        textAlignment = (textAlignment if isinstance(textAlignment, int) else
                         defaultAlignment)

        option.section = logicalIndex
        option.state = QStyle.State(int(option.state) | int(state))
        option.textAlignment = Qt.Alignment(int(textAlignment))

        option.iconAlignment = Qt.AlignVCenter
        text = model.headerData(logicalIndex, self.orientation(),
                                Qt.DisplayRole)
        text = str(text) if text is not None else ""
        option.text = text

        icon = model.headerData(logicalIndex, self.orientation(),
                                Qt.DecorationRole)
        try:
            option.icon = QIcon(icon)
        except (TypeError, ValueError):  # pragma: no cover
            pass

        margin = 2 * style.pixelMetric(QStyle.PM_HeaderMargin, None, self)

        headerArrowAlignment = style.styleHint(QStyle.SH_Header_ArrowAlignment,
                                               None, self)
        isHeaderArrowOnTheSide = headerArrowAlignment & Qt.AlignVCenter
        if self.isSortIndicatorShown() and \
                self.sortIndicatorSection() == logicalIndex \
                and isHeaderArrowOnTheSide:
            margin += style.pixelMetric(QStyle.PM_HeaderMarkSize, None, self)

        if not option.icon.isNull():
            margin += style.pixelMetric(QStyle.PM_SmallIconSize, None, self)
            margin += style.pixelMetric(QStyle.PM_HeaderMargin, None, self)

        if self.textElideMode() != Qt.ElideNone:
            elideMode = self.textElideMode()
            if hasattr(option, 'textElideMode'):  # Qt 6.0
                option.textElideMode = elideMode  # pragma: no cover
            else:
                option.text = option.fontMetrics.elidedText(
                    option.text, elideMode,
                    option.rect.width() - margin)

        foregroundBrush = model.headerData(logicalIndex, orientation,
                                           Qt.ForegroundRole)
        try:
            foregroundBrush = QBrush(foregroundBrush)
        except (TypeError, ValueError):
            pass
        else:
            option.palette.setBrush(QPalette.ButtonText, foregroundBrush)

        backgroundBrush = model.headerData(logicalIndex, orientation,
                                           Qt.BackgroundRole)
        try:
            backgroundBrush = QBrush(backgroundBrush)
        except (TypeError, ValueError):
            pass
        else:
            option.palette.setBrush(QPalette.Button, backgroundBrush)
            option.palette.setBrush(QPalette.Window, backgroundBrush)

        # the section position
        visual = self.visualIndex(logicalIndex)
        assert visual != -1
        first = self.__isFirstVisibleSection(visual)
        last = self.__isLastVisibleSection(visual)
        if first and last:
            option.position = QStyleOptionHeader.OnlyOneSection
        elif first:
            option.position = QStyleOptionHeader.Beginning
        elif last:
            option.position = QStyleOptionHeader.End
        else:
            option.position = QStyleOptionHeader.Middle
        option.orientation = orientation

        # the selected position (in QHeaderView this is always computed even if
        # highlightSections is False).
        if self.highlightSections():
            previousSelected = is_selected(self.logicalIndex(visual - 1))
            nextSelected = is_selected(self.logicalIndex(visual + 1))
        else:
            previousSelected = nextSelected = False

        if previousSelected and nextSelected:
            option.selectedPosition = QStyleOptionHeader.NextAndPreviousAreSelected
        elif previousSelected:
            option.selectedPosition = QStyleOptionHeader.PreviousIsSelected
        elif nextSelected:
            option.selectedPosition = QStyleOptionHeader.NextIsSelected
        else:
            option.selectedPosition = QStyleOptionHeader.NotAdjacent