You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

237 lines
7.1 KiB

# coding:utf-8
from PySide6.QtCore import Qt, Signal, QDate, QCalendar
from .picker_base import PickerBase, PickerPanel, PickerColumnFormatter, DigitFormatter
class DatePickerBase(PickerBase):
""" Date picker base class """
dateChanged = Signal(QDate)
def __init__(self, parent=None):
super().__init__(parent)
self.date = QDate()
self.calendar = QCalendar()
self._yearFormatter = None
self._monthFormatter = None
self._dayFormatter = None
def setDate(self, date: QDate):
""" set current date """
raise NotImplementedError
def setYearFormatter(self, formatter: PickerColumnFormatter):
self._yearFormatter = formatter
def setMonthFormatter(self, formatter: PickerColumnFormatter):
self._monthFormatter = formatter
def setDayFormatter(self, formatter: PickerColumnFormatter):
self._dayFormatter = formatter
def yearFormatter(self):
return self._yearFormatter or DigitFormatter()
def dayFormatter(self):
return self._dayFormatter or DigitFormatter()
def monthFormatter(self):
return self._monthFormatter or MonthFormatter()
class MonthFormatter(PickerColumnFormatter):
""" Month formatter """
def __init__(self):
super().__init__()
self.months = [
self.tr('January'), self.tr('February'), self.tr('March'),
self.tr('April'), self.tr('May'), self.tr('June'),
self.tr('July'), self.tr('August'), self.tr('September'),
self.tr('October'), self.tr('November'), self.tr('December')
]
def encode(self, month):
return self.months[int(month) - 1]
def decode(self, value):
return self.months.index(value) + 1
class DatePicker(DatePickerBase):
""" Date picker """
MM_DD_YYYY = 0
YYYY_MM_DD = 1
def __init__(self, parent=None, format=MM_DD_YYYY, isMonthTight=True):
"""
Parameters
----------
parent: QWidget
parent widget
format: int
the format of date, could be `DatePicker.MM_DD_YYYY` or `DatePicker.YYYY_MM_DD`
isMonthTight: bool
is the month column tight
"""
super().__init__(parent=parent)
self.MONTH = self.tr('month')
self.YEAR = self.tr('year')
self.DAY = self.tr('day')
self.isMonthTight = isMonthTight
self.setDateFormat(format)
def setDateFormat(self, format: int):
""" set the format of date
Parameters
----------
format: int
the format of date, could be `DatePicker.MM_DD_YYYY` or `DatePicker.YYYY_MM_DD`
"""
self.clearColumns()
y = QDate.currentDate().year()
self.dateFormat = format
if format == self.MM_DD_YYYY:
self.monthIndex = 0
self.dayIndex = 1
self.yearIndex = 2
self.addColumn(self.MONTH, range(1, 13),
80, Qt.AlignLeft, self.monthFormatter())
self.addColumn(self.DAY, range(1, 32),
80, formatter=self.dayFormatter())
self.addColumn(self.YEAR, range(y-100, y+101),
80, formatter=self.yearFormatter())
elif format == self.YYYY_MM_DD:
self.yearIndex = 0
self.monthIndex = 1
self.dayIndex = 2
self.addColumn(self.YEAR, range(y-100, y+101),
80, formatter=self.yearFormatter())
self.addColumn(self.MONTH, range(1, 13),
80, formatter=self.monthFormatter())
self.addColumn(self.DAY, range(1, 32), 80,
formatter=self.dayFormatter())
self.setColumnWidth(self.monthIndex, self._monthColumnWidth())
def panelInitialValue(self):
if any(self.value()):
return self.value()
date = QDate.currentDate()
y = self.encodeValue(self.yearIndex, date.year())
m = self.encodeValue(self.monthIndex, date.month())
d = self.encodeValue(self.dayIndex, date.day())
return [y, m, d] if self.dateFormat == self.YYYY_MM_DD else [m, d, y]
def setMonthTight(self, isTight: bool):
""" set whether the month column is tight """
if self.isMonthTight == isTight:
return
self.isMonthTight = isTight
self.setColumnWidth(self.monthIndex, self._monthColumnWidth())
def _monthColumnWidth(self):
fm = self.fontMetrics()
wm = max(fm.boundingRect(i).width()
for i in self.columns[self.monthIndex].items()) + 20
# don't use tight layout for english
if self.MONTH == 'month':
return wm + 49
return max(80, wm) if self.isMonthTight else wm + 49
def _onColumnValueChanged(self, panel: PickerPanel, index, value):
if index == self.dayIndex:
return
# get days number in month
month = self.decodeValue(
self.monthIndex, panel.columnValue(self.monthIndex))
year = self.decodeValue(
self.yearIndex, panel.columnValue(self.yearIndex))
days = self.calendar.daysInMonth(month, year)
# update days
c = panel.column(self.dayIndex)
day = c.currentItem().text()
self.setColumnItems(self.dayIndex, range(1, days + 1))
c.setItems(self.columns[self.dayIndex].items())
c.setSelectedItem(day)
def _onConfirmed(self, value: list):
year = self.decodeValue(self.yearIndex, value[self.yearIndex])
month = self.decodeValue(self.monthIndex, value[self.monthIndex])
day = self.decodeValue(self.dayIndex, value[self.dayIndex])
date, od = QDate(year, month, day), self.date
self.setDate(date)
if od != date:
self.dateChanged.emit(date)
def setDate(self, date: QDate):
if not date.isValid() or date.isNull():
return
self.date = date
self.setColumnValue(self.monthIndex, date.month())
self.setColumnValue(self.dayIndex, date.day())
self.setColumnValue(self.yearIndex, date.year())
self.setColumnItems(self.dayIndex, range(1, date.daysInMonth() + 1))
class ZhFormatter(PickerColumnFormatter):
""" Chinese date formatter """
suffix = ""
def encode(self, value):
return str(value) + self.suffix
def decode(self, value: str):
return int(value[:-1])
class ZhYearFormatter(ZhFormatter):
""" Chinese year formatter """
suffix = ""
class ZhMonthFormatter(ZhFormatter):
""" Chinese month formatter """
suffix = ""
class ZhDayFormatter(ZhFormatter):
""" Chinese day formatter """
suffix = ""
class ZhDatePicker(DatePicker):
""" Chinese date picker """
def __init__(self, parent=None):
super().__init__(parent, DatePicker.YYYY_MM_DD)
self.MONTH = ""
self.YEAR = ""
self.DAY = ""
self.setDayFormatter(ZhDayFormatter())
self.setYearFormatter(ZhYearFormatter())
self.setMonthFormatter(ZhMonthFormatter())
self.setDateFormat(self.YYYY_MM_DD)