from PyQt6.QtWidgets import QGraphicsScene, QGraphicsView, QSizePolicy from PyQt6 import uic, QtGui, QtCore from PyQt6.QtCore import Qt, QRect, QEvent, QCoreApplication import math #https://forum.qt.io/topic/93327/how-can-i-use-qpainter-to-paint-on-qgraphicsview/5 #https://www.pythonguis.com/tutorials/pyqt6-bitmap-graphics/#qpainter # to solve the fit problem: https://stackoverflow.com/questions/61886358/qgraphicsview-fitinview-not-working-as-expected DaySelectedEvent = QEvent.registerEventType() class CalQGraphicsView(QGraphicsView): def __init__(self, scene): super().__init__(None) self.setScene(scene) self.setMouseTracking(True) # Allow to keep track of mouse location in the scene def resizeEvent(self, event): self.fitInView(self.sceneRect(), Qt.AspectRatioMode.IgnoreAspectRatio) class CalDrawerScene(QGraphicsScene): def __init__(self, parent, env): self.parent=parent self.gridWidth=2 self.daysLabelBG="#dddddd" self.eventsLabelBG="#36e364" super().__init__(None) self.showWeekends=True self.daysRect=list() self.eventsRect=list() self.mouseOver=-1 self.env=env self.calState=env.calState self.daysNames=["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"] self.pullState() self.selection=self.today def drawForeground(self, painter, rect): origXF, origYF, widthF, heightF = rect.getRect() origXI, origYI, widthI, heightI = (int(origXF),int(origYF),int(widthF),int(heightF)) self.defaultBrush=painter.brush() self.daysRect.clear() self.eventsRect.clear() daysNamesH=self.drawDaysName(painter, origXI, origYI, widthI, heightI) self.drawGrid(painter, origXI, origYI+daysNamesH, widthI, heightI-daysNamesH) self.drawDaysLabel(painter) self.drawEvents(painter) def drawDaysName(self, painter, x, y, width, height): # Init Pen pen=QtGui.QPen() pen.setWidth(self.gridWidth) pen.setJoinStyle(Qt.PenJoinStyle.MiterJoin) po=int(self.gridWidth/2) # Pen offset painter.setPen(pen) # Init Brush painter.setBrush(Qt.BrushStyle.NoBrush) # Setup dimensions weekLength=7 font=painter.font() metric=QtGui.QFontMetrics(font); labelH=metric.boundingRect("".join(self.daysNames)).height() margin=0 offsetY=int(labelH/2)+int(labelH/4)+margin w=int((width-po*2)/weekLength) h=int(labelH) for i in range(0, 7): labelW=metric.boundingRect(self.daysNames[i]).width() offsetX=int(w/2-labelW/2) # painter.drawText(x+offsetX+w*i,y+offsetY,self.daysNames[i]) painter.drawText(x+w*i,y,w,h,Qt.AlignmentFlag.AlignHCenter,self.daysNames[i]) rect=QRect(x+po+w*i,y+po,w,h) # Draw grid painter.drawRect(rect) return labelH def drawGrid(self,painter, x, y, width, height): # Init Pen pen=QtGui.QPen() pen.setWidth(self.gridWidth) pen.setJoinStyle(Qt.PenJoinStyle.MiterJoin) po=int(self.gridWidth/2) # Pen offset painter.setPen(pen) # Init Brush brushHL=QtGui.QBrush() brushHL.setColor(QtGui.QColor("#e5e5e5")) brushHL.setStyle(Qt.BrushStyle.SolidPattern) painter.setBrush(Qt.BrushStyle.NoBrush) # Setup dimensions weekLength=7 if not self.showWeekends: weekLength=5 daysCount=weekLength*6 # brush=QtGui.QBrush() # brush.setColor(QtGui.QColor("#0000FF")) # brush.setStyle(Qt.BrushStyle.SolidPattern) w=int((width-po*2)/weekLength) h=int((height-po*2)/6) row=0 col=0 self.daysRect.clear() while row*weekLength+col=0 and b==Qt.MouseButton.LeftButton: event.accept() self.selection=self.calState.getMonthDays()[self.mouseOver] event = QEvent(DaySelectedEvent) QCoreApplication.postEvent(self.parent, event) def pullState(self): self.monthDays=self.calState.getMonthDays() self.today=self.calState.today() self.events=list() for yy, mm, dd, ww in self.monthDays: self.events.append(self.env.listEventsOn(yy,mm,dd)) class CalDrawer(): def __init__(self, parent, layout, env): self.env=env self.gs=CalDrawerScene(parent, env) self.gv=CalQGraphicsView(self.gs) # Setup propertion spLeft=QSizePolicy(QSizePolicy.Policy.Preferred,QSizePolicy.Policy.Preferred); spLeft.setHorizontalStretch(3); self.gv.setSizePolicy(spLeft); # if jean: # spLeft=QSizePolicy(QSizePolicy.Policy.Preferred,QSizePolicy.Policy.Preferred); # spLeft.setHorizontalStretch(2); # self.gv.setSizePolicy(spLeft); # else: # spLeft=QSizePolicy(QSizePolicy.Policy.Preferred,QSizePolicy.Policy.Preferred); # spLeft.setHorizontalStretch(1); # self.gv.setSizePolicy(spLeft); layout.addWidget(self.gv) def getSelectionEvents(self): (yy,mm,dd,ww)=self.gs.selection return self.env.listEventsOn(yy,mm,dd)