4 changed files with 221 additions and 2 deletions
@ -0,0 +1,143 @@
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2025 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
__all__ = ['TTkDateTime'] |
||||
|
||||
from enum import IntEnum,Enum,auto |
||||
from dataclasses import dataclass |
||||
import datetime as dt |
||||
|
||||
from typing import Optional |
||||
|
||||
from TermTk.TTkCore.color import TTkColor |
||||
from TermTk.TTkCore.string import TTkString |
||||
from TermTk.TTkCore.constant import TTkK |
||||
from TermTk.TTkCore.signal import pyTTkSignal, pyTTkSlot |
||||
from TermTk.TTkCore.TTkTerm.inputkey import TTkKeyEvent |
||||
from TermTk.TTkCore.TTkTerm.inputmouse import TTkMouseEvent |
||||
from TermTk.TTkLayouts import TTkGridLayout, TTkLayout |
||||
from TermTk.TTkWidgets.widget import TTkWidget |
||||
from TermTk.TTkWidgets.container import TTkContainer |
||||
from TermTk.TTkWidgets.spinbox import TTkSpinBox |
||||
from TermTk.TTkWidgets.datetime_date import TTkDate |
||||
from TermTk.TTkWidgets.datetime_time import TTkTime |
||||
|
||||
class TTkDateTime(TTkContainer): |
||||
''' TTkDateTime: |
||||
|
||||
A composite widget for displaying and editing date and time values. |
||||
|
||||
Combines :class:`~TermTk.TTkWidgets.datetime_date.TTkDate` and :class:`~TermTk.TTkWidgets.datetime_time.TTkTime` widgets |
||||
into a single datetime editor. |
||||
|
||||
:: |
||||
|
||||
2025/11/04 📅 12:30:45 |
||||
|
||||
.. code:: python |
||||
|
||||
import TermTk as ttk |
||||
|
||||
root = ttk.TTk(mouseTrack=True) |
||||
|
||||
ttk.TTkDateTime(parent=root) # Defaults to the current datetime |
||||
|
||||
root.mainloop() |
||||
|
||||
:param datetime: The initial datetime to display, defaults to the current datetime. |
||||
:type datetime: :py:class:`datetime.datetime`, optional |
||||
''' |
||||
|
||||
__slots__ = ( |
||||
'_datetime', |
||||
'_dateWidget', '_timeWidget', |
||||
# Signals |
||||
'datetimeChanged') |
||||
|
||||
datetimeChanged:pyTTkSignal |
||||
''' |
||||
This signal is emitted whenever the datetime changes. |
||||
|
||||
:param datetime: The new datetime value |
||||
:type datetime: :py:class:`datetime.datetime` |
||||
''' |
||||
|
||||
_datetime:dt.datetime |
||||
_dateWidget:TTkDate |
||||
_timeWidget:TTkTime |
||||
|
||||
def __init__(self, *, |
||||
datetime:Optional[dt.datetime]=None, |
||||
**kwargs) -> None: |
||||
''' |
||||
Initializes the TTkDateTime widget. |
||||
|
||||
:param datetime: The initial datetime to display. If None, the current datetime is used. |
||||
:type datetime: :py:class:`datetime.datetime`, optional |
||||
''' |
||||
self.datetimeChanged = pyTTkSignal(dt.datetime) |
||||
if not datetime: |
||||
datetime = dt.datetime.now().replace(microsecond=0) |
||||
self._datetime = datetime |
||||
_layout=TTkLayout() |
||||
size = (13+1+8,1) |
||||
super().__init__(**kwargs|{'layout':_layout, 'size':size, 'minSize':size}) |
||||
self._dateWidget = TTkDate(parent=self, pos=( 0,0), date=datetime.date()) |
||||
self._timeWidget = TTkTime(parent=self, pos=(14,0), time=datetime.time()) |
||||
self._dateWidget.dateChanged.connect(self._somethingChanged) |
||||
self._timeWidget.timeChanged.connect(self._somethingChanged) |
||||
|
||||
@pyTTkSlot() |
||||
def _somethingChanged(self) -> None: |
||||
''' |
||||
Internal slot that synchronizes the datetime value when either date or time changes. |
||||
''' |
||||
self.setDatetime( |
||||
self._datetime.combine( |
||||
date=self._dateWidget.date(), |
||||
time=self._timeWidget.time())) |
||||
|
||||
def datetime(self) -> dt.datetime: |
||||
''' |
||||
Returns the current datetime of the widget. |
||||
|
||||
:return: The current datetime |
||||
:rtype: :py:class:`datetime.datetime` |
||||
''' |
||||
return self._datetime |
||||
|
||||
@pyTTkSlot(dt.datetime) |
||||
def setDatetime(self, datetime:dt.datetime) -> None: |
||||
''' |
||||
Sets the current datetime of the widget. |
||||
|
||||
This updates both the internal date and time widgets and emits the |
||||
:py:attr:`datetimeChanged` signal if the value changes. |
||||
|
||||
:param datetime: The new datetime to set |
||||
:type datetime: :py:class:`datetime.datetime` |
||||
''' |
||||
if datetime != self._datetime: |
||||
self._datetime = datetime |
||||
self._dateWidget.setDate(datetime.date()) |
||||
self._timeWidget.setTime(datetime.time()) |
||||
self.datetimeChanged.emit(datetime) |
||||
@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2021 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
import sys, os |
||||
from datetime import time,date,datetime |
||||
|
||||
sys.path.append(os.path.join(sys.path[0],'../../libs/pyTermTk')) |
||||
import TermTk as ttk |
||||
|
||||
root = ttk.TTk(mouseTrack=True) |
||||
winLog = ttk.TTkWindow(parent=root, pos=(20,1), size=(80,30), layout=ttk.TTkGridLayout()) |
||||
ttk.TTkLogViewer(parent=winLog) |
||||
|
||||
win = ttk.TTkWindow(parent=root, pos=( 0,0), size=(57,14), title='Generic') |
||||
win1 = ttk.TTkWindow(parent=root, pos=( 60,0), size=(22,12), title='Date Form', layout=ttk.TTkGridLayout()) |
||||
win2 = ttk.TTkWindow(parent=root, pos=( 85,0), size=(15,12), title='Date') |
||||
win3 = ttk.TTkWindow(parent=root, pos=(103,0), size=(25,12), title='DateTime') |
||||
|
||||
testTime1=time(hour=3,minute=30) |
||||
timeWidget1 = ttk.TTkTime(parent=win, pos=(1,0), time=testTime1) |
||||
timeWidget2 = ttk.TTkTime(parent=win, pos=(1,2)) |
||||
|
||||
timeLabel1 = ttk.TTkLabel(parent=win, pos=(1,4), text=str(testTime1)) |
||||
timeLabel2 = ttk.TTkLabel(parent=win, pos=(1,6), text=str(timeWidget2.time())) |
||||
timeWidget1.timeChanged.connect(lambda _t:timeLabel1.setText(str(_t))) |
||||
timeWidget2.timeChanged.connect(lambda _t:timeLabel2.setText(str(_t))) |
||||
|
||||
testDate = date(year=1980, month=12, day=25) |
||||
dateFormWidget1 = ttk.TTkDateForm(parent=win, pos=(12,0), date=testDate) |
||||
dateFormWidget2 = ttk.TTkDateForm(parent=win, pos=(34,0)) |
||||
dateFormWidget3 = ttk.TTkDateForm(parent=win1, date=testDate.replace(year=2000)) |
||||
dateLabel = ttk.TTkLabel(parent=win, pos=(1,8), text=str(testDate)) |
||||
dateFormWidget1.dateChanged.connect(lambda _d: dateLabel.setText(str(_d))) |
||||
dateFormWidget1.dateChanged.connect(dateFormWidget2.setDate) |
||||
dateFormWidget2.dateChanged.connect(dateFormWidget1.setDate) |
||||
dateFormWidget3.dateChanged.connect(dateFormWidget2.setDate) |
||||
|
||||
dateWidget1 = ttk.TTkDate(parent=win2, pos=(0,0), date=testDate) |
||||
dateWidget2 = ttk.TTkDate(parent=win2, pos=(0,2)) |
||||
dateLabel1 = ttk.TTkLabel(parent=win2, pos=(0,4), text=str(testDate)) |
||||
dateLabel2 = ttk.TTkLabel(parent=win2, pos=(0,6), text=str(dateWidget2.date())) |
||||
dateWidget1.dateChanged.connect(lambda _d:dateLabel1.setText(str(_d))) |
||||
dateWidget1.dateChanged.connect(dateFormWidget1.setDate) |
||||
dateWidget2.dateChanged.connect(lambda _d:dateLabel2.setText(str(_d))) |
||||
|
||||
testDatetime = datetime(1995,10,5, 23,30,5) |
||||
dateTimeWidget1 = ttk.TTkDateTime(parent=win3, pos=(0,0)) |
||||
dateTimeWidget2 = ttk.TTkDateTime(parent=win3, pos=(0,4), datetime=testDatetime) |
||||
datetimeLabel1 = ttk.TTkLabel(parent=win3, pos=(0,2), text=str(dateTimeWidget1.datetime())) |
||||
datetimeLabel2 = ttk.TTkLabel(parent=win3, pos=(0,6), text=str(testDatetime)) |
||||
dateTimeWidget1.datetimeChanged.connect(lambda _d:datetimeLabel1.setText(str(_d))) |
||||
dateTimeWidget1.datetimeChanged.connect(dateTimeWidget2.setDatetime) |
||||
dateTimeWidget2.datetimeChanged.connect(lambda _d:datetimeLabel2.setText(str(_d))) |
||||
|
||||
root.mainloop() |
||||
Loading…
Reference in new issue