def __init__( self, parent = None ): super(XCalendarScene, self).__init__( parent ) # define custom properties self._currentDate = QDate.currentDate() self._currentMode = XCalendarScene.Mode.Month self._timelineScale = XCalendarScene.TimelineScale.Week self._minimumDate = QDate() self._maximumDate = QDate() self._dateGrid = {} self._dateTimeGrid = {} self._buildData = {} self._rebuildRequired = False
def dateAt( self, point ): """ Returns the date at the given point. :param point | <QPoint> """ for date, data in self._dateGrid.items(): if ( data[1].contains(point) ): return QDate.fromJulianDay(date) return QDate()
def rebuild( self ): """ Rebuilds the information for this scene. """ self._buildData.clear() self._dateGrid.clear() self._dateTimeGrid.clear() curr_min = self._minimumDate curr_max = self._maximumDate self._maximumDate = QDate() self._minimumDate = QDate() self.markForRebuild(False) # rebuilds the month view if ( self.currentMode() == XCalendarScene.Mode.Month ): self.rebuildMonth() elif ( self.currentMode() in (XCalendarScene.Mode.Week, XCalendarScene.Mode.Day)): self.rebuildDays() # rebuild the items in the scene items = sorted(self.items()) for item in items: item.setPos(0, 0) item.hide() for item in items: if ( isinstance(item, XCalendarItem) ): item.rebuild() if ( curr_min != self._minimumDate or curr_max != self._maximumDate ): parent = self.parent() if ( parent and not parent.signalsBlocked() ): parent.dateRangeChanged.emit(self._minimumDate, self._maximumDate)
def setDateEnd(self, dateEnd): """ Sets the end date for this item. This method will only affect the start date if the end date is set to occur before its start, in which case it will set the start date as the same date. (1 day duration) Otherwise, this method will scale the duration of the event. :param dateEnd | <QDate> """ dateEnd = QDate(dateEnd) if (dateEnd < self._dateStart): self._dateStart = dateEnd self._dateEnd = dateEnd self.markForRebuild()
def setDateStart(self, dateStart): """ Sets the start date for this item. This will automatically push the end date to match the duration for this item. So if the item starts on 1/1/12 and ends on 1/2/12, and the start date is changed to 2/1/12, the end date will change to 2/2/12. To affect the duration of the item, use either setDuration, or setDateEnd. :param dateStart | <QDate> """ dateStart = QDate(dateStart) duration = self.duration() self._dateStart = dateStart self._dateEnd = dateStart.addDays(duration - 1) self.markForRebuild()
def setValue(self, value): self.setDate(QDate(value))
def rebuildMonth( self ): """ Rebuilds the month for this scene. """ # make sure we start at 0 for sunday vs. 7 for sunday day_map = dict([(i+1, i+1) for i in range(7)]) day_map[7] = 0 today = QDate.currentDate() curr = self.currentDate() first = QDate(curr.year(), curr.month(), 1) last = QDate(curr.year(), curr.month(), curr.daysInMonth()) first = first.addDays(-day_map[first.dayOfWeek()]) last = last.addDays(6-day_map[last.dayOfWeek()]) cols = 7 rows = (first.daysTo(last) + 1) / cols hlines = [] vlines = [] padx = 6 pady = 6 header = 24 w = self.width() - (2 * padx) h = self.height() - (2 * pady) dw = (w / cols) - 1 dh = ((h - header) / rows) - 1 x0 = padx y0 = pady + header x = x0 y = y0 for row in range(rows + 1): hlines.append(QLine(x0, y, w, y)) y += dh for col in range(cols + 1): vlines.append(QLine(x, y0, x, h)) x += dw self._buildData['grid'] = hlines + vlines # draw the date fields date = first row = 0 col = 0 # draw the headers x = x0 y = pady regular_text = [] mid_text = [] self._buildData['regular_text'] = regular_text self._buildData['mid_text'] = mid_text for day in ('Sun', 'Mon','Tue','Wed','Thu','Fri','Sat'): regular_text.append((x + 5, y, dw, y0, Qt.AlignLeft | Qt.AlignVCenter, day)) x += dw for i in range(first.daysTo(last) + 1): top = (y0 + (row * dh)) left = (x0 + (col * dw)) rect = QRectF(left - 1, top, dw, dh) # mark the current date on the calendar if ( date == curr ): self._buildData['curr_date'] = rect # mark today's date on the calendar elif ( date == today ): self._buildData['today'] = rect # determine how to draw the calendar format = 'd' if ( date.day() == 1 ): format = 'MMM d' # determine the color to draw the text if ( date.month() == curr.month() ): text = regular_text else: text = mid_text # draw the text text.append((left + 2, top + 2, dw - 4, dh - 4, Qt.AlignTop | Qt.AlignLeft, date.toString(format))) # update the limits if ( not i ): self._minimumDate = date self._maximumDate = date self._dateGrid[date.toJulianDay()] = ((row, col), rect) if ( col == (cols - 1) ): row += 1 col = 0 else: col += 1 date = date.addDays(1)