def datetimeAt(self, x): """ Returns the datetime at the inputed x position. :return <QDateTime> """ gantt = self.ganttWidget() dstart = gantt.dateTimeStart() distance = int(x / float(gantt.cellWidth())) # calculate the time for a minute if scale == gantt.Timescale.Minute: return dstart.addSecs(distance) # calculate the time for an hour elif scale == gantt.Timescale.Hour: return dstart.addSecs(distance * 2.0) # calculate the time for a day elif scale == gantt.Timescale.Day: dstart = QDateTime(gantt.dateStart(), QTime(0, 0, 0)) return dstart.addSecs(distance * (60 * 2.0)) # calculate the time off the date only else: date = self.dateAt(x) return QDateTime(date, QTime(0, 0, 0))
def setTimeEnd(self, timeEnd): """ Sets the end time for this item. This method will only affect the start time if the end time is set to occur before its start, in which case it will set the start time as 60 minutes before. Otherwise, this method will scale the duration of the event. :param timeEnd | <QTime> """ timeEnd = QTime(timeEnd) if (timeEnd < self._timeStart): self._timeStart = timeEnd.addSecs(-60 * 60) self._timeEnd = timeEnd self.markForRebuild()
def setTimeEnd( self, timeEnd ): """ Sets the end time for this item. This method will only affect the start time if the end time is set to occur before its start, in which case it will set the start time as 60 minutes before. Otherwise, this method will scale the duration of the event. :param timeEnd | <QTime> """ timeEnd = QTime(timeEnd) if ( timeEnd < self._timeStart ): self._timeStart = timeEnd.addSecs(-60 * 60) self._timeEnd = timeEnd self.markForRebuild()
def setTimeStart( self, timeStart ): """ Sets the start time for this item. This will automatically push the end time to match the length for this item. So if the item starts at 11a and ends on 1p, and the start time is changed to 12p the end time will change to 2p. To affect the length of the item, use either setLength, or setTimeEnd. :param timeStart | <QDate> """ timeStart = QTime(timeStart) length = self.length() # in minutes self._timeStart = timeStart self._timeEnd = timeStart.addSecs(length * 60) self.markForRebuild()
def datetimeXPos(self, dtime): """ Returns the x-position for the inputed date time. :return <float> """ gantt = self.ganttWidget() scale = gantt.timescale() # calculate the distance for a minute if scale == gantt.Timescale.Minute: dstart = gantt.dateTimeStart() secs = dstart.secsTo(dtime) return secs # calculate the distance for an hour elif scale == gantt.Timescale.Hour: dstart = gantt.dateTimeStart() secs = dstart.secsTo(dtime) return secs / 2.0 # calculate the distance for a day elif scale == gantt.Timescale.Day: dstart = QDateTime(gantt.dateStart(), QTime(0, 0, 0)) secs = dstart.secsTo(dtime) return (secs / (60.0 * 2.0)) # calculate the distance off the date only else: return self.dateXPos(dtime.date())
def setTimeStart(self, timeStart): """ Sets the start time for this item. This will automatically push the end time to match the length for this item. So if the item starts at 11a and ends on 1p, and the start time is changed to 12p the end time will change to 2p. To affect the length of the item, use either setLength, or setTimeEnd. :param timeStart | <QDate> """ timeStart = QTime(timeStart) length = self.length() # in minutes self._timeStart = timeStart self._timeEnd = timeStart.addSecs(length * 60) self.markForRebuild()
def timeEnd(self): """ Returns the ending time that will be used for this item. If it is an all day event, then the time returned will be 23:59:59. :return <QTime> """ if (self.isAllDay()): return QTime(23, 59, 59) return self._timeEnd
def timeStart(self): """ Returns the starting time that will be used for this item. If it is an all day event, then the time returned will be 0:0:0 :return <QTime> """ if (self.isAllDay()): return QTime(0, 0, 0) return self._timeStart
def setDateTimeStart(self, dtime): """ Sets the starting date time for this gantt chart. :param dtime | <QDateTime> """ self._dateStart = dtime.date() if self.timescale() in (self.Timescale.Minute, self.Timescale.Hour): self._timeStart = dtime.time() else: self._timeStart = QTime(0, 0, 0)
def setDateTimeEnd(self, dtime): """ Sets the endiing date time for this gantt chart. :param dtime | <QDateTime> """ self._dateEnd = dtime.date() if self.timescale() in (self.Timescale.Minute, self.Timescale.Hour): self._timeEnd = dtime.time() else: self._timeEnd = QTime(23, 59, 59)
def setTimescale(self, timescale): """ Sets the timescale value for this widget to the inputed value. :param timescale | <XGanttWidget.Timescale> """ self._timescale = timescale # show hour/minute scale if timescale == XGanttWidget.Timescale.Minute: self._cellWidth = 60 # (60 seconds) self._dateStart = QDate.currentDate() self._timeStart = QTime(0, 0, 0) self._dateEnd = QDate.currentDate() self._timeEnd = QTime(23, 59, 59) elif timescale == XGanttWidget.Timescale.Hour: self._cellWidth = 30 # (60 seconds / 2.0) self._dateStart = QDate.currentDate() self._timeStart = QTime(0, 0, 0) self._dateEnd = QDate.currentDate() self._timeEnd = QTime(23, 59, 59) # show day/hour scale elif timescale == XGanttWidget.Timescale.Day: self._cellWidth = 30 # (60 minutes / 2.0) self._dateStart = QDate.currentDate().addDays(-7) self._timeStart = QTime(0, 0, 0) self._dateEnd = QDate.currentDate().addDays(7) self._timeEnd = QTime(23, 59, 59)
def __init__(self, ganttWidget): super(XGanttWidgetItem, self).__init__() # set default properties self.setFixedHeight(ganttWidget.cellHeight()) for i in range(1, 20): self.setTextAlignment(i, Qt.AlignCenter) # define custom properties self._blockedAdjustments = {} self._viewItem = self.createViewItem() self._dateStart = QDate.currentDate() self._dateEnd = QDate.currentDate() self._allDay = True self._timeStart = QTime(0, 0, 0) self._timeEnd = QTime(23, 59, 59) self._name = '' self._properties = {} self._itemStyle = XGanttWidgetItem.ItemStyle.Normal self._useGroupStyleWithChildren = True self._dependencies = {} self._reverseDependencies = {}
def __init__( self ): super(XCalendarItem, self).__init__() curr_dtime = QDateTime.currentDateTime() curr_date = curr_dtime.date() curr_time = curr_dtime.time() self.setFlags(self.flags() | self.ItemIsSelectable) self.setAcceptHoverEvents(True) # round to the nearest 15 minute segment curr_time = QTime(curr_time.hour(), curr_time.minute() - curr_time.minute() % 30, 0) self._rebuildBlocked = False self._textData = [] self._customData = {} self._textColor = QColor('white') self._fillColor = QColor('blue') self._borderColor = QColor('blue') self._highlightColor = QColor('blue') self._title = 'No Title' self._description = '' self._dateStart = curr_date self._dateEnd = curr_date self._timeStart = curr_time self._timeEnd = curr_time.addSecs(60 * 60) self._allDay = True self._rebuildRequired = False if ( QTime(23, 0, 0) <= self._timeStart ): self._timeEnd = QTime(23, 59, 0) self.setColor('blue')
def __init__(self): super(XCalendarItem, self).__init__() curr_dtime = QDateTime.currentDateTime() curr_date = curr_dtime.date() curr_time = curr_dtime.time() self.setFlags(self.flags() | self.ItemIsSelectable) self.setAcceptHoverEvents(True) # round to the nearest 15 minute segment curr_time = QTime(curr_time.hour(), curr_time.minute() - curr_time.minute() % 30, 0) self._rebuildBlocked = False self._textData = [] self._customData = {} self._textColor = QColor('white') self._fillColor = QColor('blue') self._borderColor = QColor('blue') self._highlightColor = QColor('blue') self._title = 'No Title' self._description = '' self._dateStart = curr_date self._dateEnd = curr_date self._timeStart = curr_time self._timeEnd = curr_time.addSecs(60 * 60) self._allDay = True self._rebuildRequired = False if (QTime(23, 0, 0) <= self._timeStart): self._timeEnd = QTime(23, 59, 0) self.setColor('blue')
def rebuildDay(self, opt): """ Rebuilds the scale for the day mode. :param opt | <XGanttRenderOptions> """ self._labels = [] self._hlines = [] self._vlines = [] self._weekendRects = [] self._alternateRects = [] self._topLabels = [] top_format = 'dddd MMMM dd' label_format = 'ha' increment = 60 # hour # generate vertical lines x = 0 i = 0 half = opt.header_height / 2.0 curr = QDateTime(opt.start, QTime(0, 0, 0)) end = QDateTime(opt.end, QTime(23, 0, 0)) top_label = opt.start.toString(top_format) top_rect = QRect(0, 0, 0, half) alt_rect = None while curr <= end: # update the top rect new_top_label = curr.toString(top_format) if new_top_label != top_label: top_rect.setRight(x) self._topLabels.append((top_rect, top_label)) top_rect = QRect(x, 0, 0, half) top_label = new_top_label if alt_rect is not None: alt_rect.setRight(x) self._alternateRects.append(alt_rect) alt_rect = None else: alt_rect = QRect(x, 0, 0, opt.height) # create the line self._hlines.append(QLine(x, 0, x, opt.height)) # create the header label/rect label = nativestring(curr.toString(label_format))[:-1] rect = QRect(x, half, opt.cell_width, half) self._labels.append((rect, label)) # increment the dates curr = curr.addSecs(increment * 60) x += opt.cell_width i += 1 # update the top rect top_rect.setRight(x) top_label = opt.end.toString(top_format) self._topLabels.append((top_rect, top_label)) if alt_rect is not None: alt_rect.setRight(x) self._alternateRects.append(alt_rect) # resize the width to match the last date range new_width = x self.setSceneRect(0, 0, new_width, opt.height) # generate horizontal lines y = 0 h = opt.height width = new_width while y < h: self._vlines.append(QLine(0, y, width, y)) y += opt.cell_height # clear the dirty flag self._dirty = False
def rebuildDays( self ): """ Rebuilds the interface as a week display. """ time = QTime(0, 0, 0) hour = True x = 6 y = 6 + 24 w = self.width() - 12 - 25 dh = 48 indent = 58 text_data = [] vlines = [] hlines = [QLine(x, y, w, y)] time_grids = [] for i in range(48): if ( hour ): hlines.append(QLine(x, y, w, y)) text_data.append((x, y + 6, indent - 6, dh, Qt.AlignRight | Qt.AlignTop, time.toString('hap'))) else: hlines.append(QLine(x + indent, y, w, y)) time_grids.append((time, y, dh / 2)) # move onto the next line hour = not hour time = time.addSecs(30 * 60) y += dh / 2 hlines.append(QLine(x, y, w, y)) h = y y = 6 + 24 # load the grid vlines.append(QLine(x, y, x, h)) vlines.append(QLine(x + indent, y, x + indent, h)) vlines.append(QLine(w, y, w, h)) today = QDate.currentDate() curr_date = self.currentDate() # load the days if ( self.currentMode() == XCalendarScene.Mode.Week ): date = self.currentDate() day_of_week = date.dayOfWeek() if ( day_of_week == 7 ): day_of_week = 0 min_date = date.addDays(-day_of_week) max_date = date.addDays(6-day_of_week) self._minimumDate = min_date self._maximumDate = max_date dw = (w - (x + indent)) / 7.0 vx = x + indent date = min_date for i in range(7): vlines.append(QLine(vx, y, vx, h)) text_data.append((vx + 6, 6, dw, 24, Qt.AlignCenter, date.toString('ddd MM/dd'))) self._dateGrid[date.toJulianDay()] = ((0, i), QRectF(vx, y, dw, h - y)) # create the date grid for date time options for r, data in enumerate(time_grids): time, ty, th = data dtime = QDateTime(date, time) key = dtime.toTime_t() self._dateTimeGrid[key] = ((r, i), QRectF(vx, ty, dw, th)) if ( date == curr_date ): self._buildData['curr_date'] = QRectF(vx, y, dw, h - 29) elif ( date == today ): self._buildData['today'] = QRectF(vx, y, dw, h - 29) date = date.addDays(1) vx += dw # load a single day else: date = self.currentDate() self._maximumDate = date self._minimumDate = date text_data.append((x + indent, 6, w, 24, Qt.AlignCenter, date.toString('ddd MM/dd'))) self._dateGrid[date.toJulianDay()] = ((0, 0), QRectF(x, y, w - x, h - y)) # create the date grid for date time options for r, data in enumerate(time_grids): time, ty, th = data dtime = QDateTime(date, time) key = dtime.toTime_t() rect = QRectF(x + indent, ty, w - (x + indent), th) self._dateTimeGrid[key] = ((r, 0), rect) self._buildData['grid'] = hlines + vlines self._buildData['regular_text'] = text_data rect = self.sceneRect() rect.setHeight(h + 6) super(XCalendarScene, self).setSceneRect(rect)
def __init__(self, parent=None): super(XGanttWidget, self).__init__(parent) # load the user interface projexui.loadUi(__file__, self) # define custom properties self._backend = None self._dateStart = QDate.currentDate().addMonths(-2) self._dateEnd = QDate.currentDate().addMonths(2) self._timeStart = QTime(0, 0, 0) self._timeEnd = QTime(23, 59, 59) self._alternatingRowColors = False self._cellWidth = 20 self._cellHeight = 20 self._first = True self._dateFormat = 'M/d/yy' self._timescale = XGanttWidget.Timescale.Month self._scrolling = False self._dirty = False # setup the palette colors palette = self.palette() color = palette.color(palette.Base) self._gridPen = QPen(color.darker(115)) self._brush = QBrush(color) self._alternateBrush = QBrush(color.darker(105)) weekendColor = color.darker(108) self._weekendBrush = QBrush(weekendColor) # setup the columns for the tree self.setColumns(['Name', 'Start', 'End', 'Calendar Days', 'Work Days']) header = self.uiGanttTREE.header() header.setFixedHeight(self._cellHeight * 2) headerItem = self.uiGanttTREE.headerItem() headerItem.setSizeHint(0, QSize(80, header.height())) # initialize the tree widget self.uiGanttTREE.setShowGrid(False) self.uiGanttTREE.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.uiGanttTREE.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.uiGanttTREE.setVerticalScrollMode(self.uiGanttTREE.ScrollPerPixel) self.uiGanttTREE.setResizeToContentsInteractive(True) self.uiGanttTREE.setEditable(True) self.uiGanttTREE.resize(500, 20) self.uiGanttTREE.setContextMenuPolicy(Qt.CustomContextMenu) # initialize the view widget self.uiGanttVIEW.setDragMode(self.uiGanttVIEW.RubberBandDrag) self.uiGanttVIEW.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.uiGanttVIEW.setAlignment(Qt.AlignTop | Qt.AlignLeft) self.uiGanttVIEW.setScene(XGanttScene(self)) self.uiGanttVIEW.installEventFilter(self) self.uiGanttVIEW.horizontalScrollBar().setValue(50) self.uiGanttVIEW.setContextMenuPolicy(Qt.CustomContextMenu) # create connections self.uiGanttTREE.itemExpanded.connect(self.syncView) self.uiGanttTREE.itemCollapsed.connect(self.syncView) # connect scrollbars tree_bar = self.uiGanttTREE.verticalScrollBar() view_bar = self.uiGanttVIEW.verticalScrollBar() tree_bar.rangeChanged.connect(self._updateViewRect) tree_bar.valueChanged.connect(self._scrollView) view_bar.valueChanged.connect(self._scrollTree) # connect selection self.uiGanttTREE.itemSelectionChanged.connect(self._selectView) self.uiGanttVIEW.scene().selectionChanged.connect(self._selectTree) self.uiGanttTREE.itemChanged.connect(self.updateItemData) self.uiGanttTREE.customContextMenuRequested.connect( self.requestTreeMenu) self.uiGanttVIEW.customContextMenuRequested.connect( self.requestViewMenu)
def setValue(self, value): self.setTime(QTime(value))