Streeter
Streeter

Reputation: 72

Can't PaintCell after using QItemDelegate to change date position for a QCalendarWidget

I am trying to override QCalendarWidget's paintCell() method to paint a red outline on today's date cell and draw events that will be defined by the user. For my calendar, I used a QItemDelegate to change the alignment of the date flags so I would have more room to draw events. However, I can't seem to get both the QItemDelegate and paintCell() working together. I can only have one or the other work at one time. If I try to do both, only the Delegate shows and nothing is painted.

from PySide2.QtWidgets import QMainWindow, QCalendarWidget, QApplication, QItemDelegate, QTableView
from PySide2.QtGui import QPen
from PySide2.QtCore import Qt
import sys


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__()
        self.calendar = CustomCalendar()
        self.calendarview = self.calendar.findChild(QTableView, "qt_calendar_calendarview")
        self.calendardelegate = CalendarItemDelegate(self.calendarview)
        self.calendarview.setItemDelegate(self.calendardelegate)
        self.setCentralWidget(self.calendar)
        self.show()


class CustomCalendar(QCalendarWidget):
    def __init__(self, parent=None):
        super().__init__()

    def paintCell(self, painter, rect, date):
        QCalendarWidget.paintCell(self, painter, rect, date)
        pen = QPen()
        pen.setColor(Qt.red)
        painter.setPen(pen)
        if date == date.currentDate():
            painter.save()
            painter.drawRect(rect.adjusted(0, 0, -1, -1))
            painter.restore()


class CalendarItemDelegate(QItemDelegate):
    def paint(self, painter, option, index):
        painter._date_flag = index.row() > 0
        super().paint(painter, option, index)

    def drawDisplay(self, painter, option, rect, text):
        if painter._date_flag:
            option.displayAlignment = Qt.AlignTop | Qt.AlignLeft
        super().drawDisplay(painter, option, rect, text)


app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()

How can I get both to work at once?

enter image description here

Delegate

enter image description here

PaintCell

Upvotes: 0

Views: 329

Answers (1)

musicamante
musicamante

Reputation: 48231

When a custom item delegate is set on the calendar widget, the default paintCell is just ignored, as it's responsibility of the (private) delegate to call it.

Since you're using a QItemDelegate, you can take advantage of the drawFocus() function and check if the option.state has the State_Selected flag set (technically, you could do it in the drawDisplay() too, since the function is called anyway and the option has the same values):

    def drawFocus(self, painter, option, rect):
        super().drawFocus(painter, option, rect)
        if option.state & QStyle.State_Selected:
            painter.save()
            painter.setPen(Qt.red)
            painter.drawRect(rect.adjusted(0, 0, -1, -1))
            painter.restore()

Upvotes: 1

Related Questions