Browse Source

refactor: Improve typing (#535)

pull/540/head
Pier CeccoPierangioliEugenio 4 months ago committed by GitHub
parent
commit
2885f21bc4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 8
      demo/showcase/formwidgets01.py
  2. 8
      demo/showcase/formwidgets02.py
  3. 22
      libs/pyTermTk/TermTk/TTkCore/constant.py
  4. 8
      libs/pyTermTk/TermTk/TTkCore/helper.py
  5. 10
      libs/pyTermTk/TermTk/TTkWidgets/checkbox.py
  6. 104
      libs/pyTermTk/TermTk/TTkWidgets/combobox.py
  7. 2
      libs/pyTermTk/TermTk/TTkWidgets/datetime_time.py
  8. 10
      libs/pyTermTk/TermTk/TTkWidgets/frame.py
  9. 177
      libs/pyTermTk/TermTk/TTkWidgets/lineedit.py
  10. 8
      tests/t.ui/test.ui.009.widgets.form.py
  11. 11
      tools/check.import.sh

8
demo/showcase/formwidgets01.py

@ -62,14 +62,14 @@ def demoFormWidgets(root=None):
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='Line Edit Test 3 oަ -'),row,2)
row += 1; win_form1_grid_layout.addWidget(ttk.TTkLabel(text='Line Edit Input Number'),row,0)
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='123456', inputType=ttk.TTkK.Input_Number),row,2)
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='123456', inputType=ttk.TTkK.InputType.Input_Number),row,2)
row += 1; win_form1_grid_layout.addWidget(ttk.TTkLabel(text='Line Edit Input Wrong Number'),row,0)
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='No num Text', inputType=ttk.TTkK.Input_Number),row,2)
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='No num Text', inputType=ttk.TTkK.InputType.Input_Number),row,2)
row += 1; win_form1_grid_layout.addWidget(ttk.TTkLabel(text='Line Edit Input Password'),row,0)
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='Password', inputType=ttk.TTkK.Input_Password),row,2)
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='Password', inputType=ttk.TTkK.InputType.Input_Password),row,2)
row += 1; win_form1_grid_layout.addWidget(ttk.TTkLabel(text='Line Edit Number Password'),row,0)
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='Password', inputType=ttk.TTkK.Input_Password+ttk.TTkK.Input_Number),row,2)
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='Password', inputType=ttk.TTkK.InputType.Input_Password|ttk.TTkK.InputType.Input_Number),row,2)
row += 1; win_form1_grid_layout.addWidget(ttk.TTkLabel(text='Spinbox (default [0,99])'),row,0)
win_form1_grid_layout.addWidget(ttk.TTkSpinBox(),row,2)

8
demo/showcase/formwidgets02.py

@ -76,17 +76,17 @@ def demoFormWidgets(root=None):
win_form1_grid_layout.addWidget(_en_dis_cb := ttk.TTkCheckbox(text=" en/dis", checked=True),row,3); _en_dis_cb.clicked.connect(_wid.setEnabled)
row += 1; win_form1_grid_layout.addWidget(ttk.TTkLabel(text='Line Edit Input Number'),row,0)
win_form1_grid_layout.addWidget(_wid := ttk.TTkLineEdit(text='123456', inputType=ttk.TTkK.Input_Number),row,2)
win_form1_grid_layout.addWidget(_wid := ttk.TTkLineEdit(text='123456', inputType=ttk.TTkK.InputType.Input_Number),row,2)
win_form1_grid_layout.addWidget(_en_dis_cb := ttk.TTkCheckbox(text=" en/dis", checked=True),row,3); _en_dis_cb.clicked.connect(_wid.setEnabled)
row += 1; win_form1_grid_layout.addWidget(ttk.TTkLabel(text='Line Edit Input Wrong Number'),row,0)
win_form1_grid_layout.addWidget(_wid := ttk.TTkLineEdit(text='No num Text', inputType=ttk.TTkK.Input_Number),row,2)
win_form1_grid_layout.addWidget(_wid := ttk.TTkLineEdit(text='No num Text', inputType=ttk.TTkK.InputType.Input_Number),row,2)
win_form1_grid_layout.addWidget(_en_dis_cb := ttk.TTkCheckbox(text=" en/dis", checked=True),row,3); _en_dis_cb.clicked.connect(_wid.setEnabled)
row += 1; win_form1_grid_layout.addWidget(ttk.TTkLabel(text='Line Edit Input Password'),row,0)
win_form1_grid_layout.addWidget(_wid := ttk.TTkLineEdit(text='Password', inputType=ttk.TTkK.Input_Password),row,2)
win_form1_grid_layout.addWidget(_wid := ttk.TTkLineEdit(text='Password', inputType=ttk.TTkK.InputType.Input_Password),row,2)
win_form1_grid_layout.addWidget(_en_dis_cb := ttk.TTkCheckbox(text=" en/dis", checked=True),row,3); _en_dis_cb.clicked.connect(_wid.setEnabled)
row += 1; win_form1_grid_layout.addWidget(ttk.TTkLabel(text='Line Edit Number Password'),row,0)
win_form1_grid_layout.addWidget(_wid := ttk.TTkLineEdit(text='Password', inputType=ttk.TTkK.Input_Password+ttk.TTkK.Input_Number),row,2)
win_form1_grid_layout.addWidget(_wid := ttk.TTkLineEdit(text='Password', inputType=ttk.TTkK.InputType.Input_Password|ttk.TTkK.InputType.Input_Number),row,2)
win_form1_grid_layout.addWidget(_en_dis_cb := ttk.TTkCheckbox(text=" en/dis", checked=True),row,3); _en_dis_cb.clicked.connect(_wid.setEnabled)
row += 1; win_form1_grid_layout.addWidget(ttk.TTkLabel(text='Spinbox (default [0,99])'),row,0)

22
libs/pyTermTk/TermTk/TTkCore/constant.py

@ -194,7 +194,7 @@ class TTkConstant:
Background=0x02
'''The color type returned is Background'''
class CheckState(int):
class CheckState(IntEnum):
''' This class type is used to describe the check status.
.. autosummary::
@ -213,7 +213,7 @@ class TTkConstant:
PartiallyChecked = CheckState.PartiallyChecked
Checked = CheckState.Checked
class InsertPolicy(int):
class InsertPolicy(IntEnum):
'''Specifies what the :py:class:`TTkComboBox` should do when a new string is entered by the user.
.. autosummary::
@ -423,10 +423,26 @@ class TTkConstant:
Cursor_Blinking_Bar = 0x0006
Cursor_Steady_Bar = 0x0007
# Input types
class InputType(Flag):
'''
This enum type describes the input validation types for text input widgets.
.. autosummary::
Input_Text
Input_Number
Input_Password
'''
Input_Text = 0x01
'''Accept any text input (default)'''
Input_Number = 0x02
'''Accept only numeric input (integers and decimals)'''
Input_Password = 0x04
'''Password input type (deprecated - use :py:class:`TTkLineEdit.EchoMode.Password` instead)'''
# Input types
Input_Text = InputType.Input_Text
Input_Number = InputType.Input_Number
Input_Password = InputType.Input_Password
# Alignment
class Alignment(IntEnum):

8
libs/pyTermTk/TermTk/TTkCore/helper.py

@ -127,7 +127,7 @@ class TTkHelper:
return TTkGlbl.term_w, TTkGlbl.term_h
@staticmethod
def rootOverlay(widget: TTkWidget) -> Optional[TTkWidget]:
def rootOverlay(widget: Optional[TTkWidget]) -> Optional[TTkWidget]:
if not widget:
return None
if not TTkHelper._overlay:
@ -174,7 +174,7 @@ class TTkHelper:
return False
@staticmethod
def isOverlay(widget: TTkWidget) -> bool:
def isOverlay(widget: Optional[TTkWidget]) -> bool:
return TTkHelper.rootOverlay(widget) is not None
@staticmethod
@ -241,8 +241,8 @@ class TTkHelper:
bkFocus.setFocus()
@staticmethod
def removeOverlayAndChild(widget: TTkWidget) -> None:
if not TTkHelper._rootWidget:
def removeOverlayAndChild(widget: Optional[TTkWidget]) -> None:
if not TTkHelper._rootWidget or not widget:
return
if not TTkHelper.isOverlay(widget):
return

10
libs/pyTermTk/TermTk/TTkWidgets/checkbox.py

@ -22,11 +22,13 @@
__all__ = ['TTkCheckbox']
from typing import Optional
from TermTk.TTkCore.constant import TTkK
from TermTk.TTkCore.cfg import TTkCfg
from TermTk.TTkCore.color import TTkColor
from TermTk.TTkCore.canvas import TTkCanvas
from TermTk.TTkCore.string import TTkString
from TermTk.TTkCore.string import TTkString, TTkStringType
from TermTk.TTkCore.signal import pyTTkSignal, pyTTkSlot
from TermTk.TTkCore.TTkTerm.inputkey import TTkKeyEvent
from TermTk.TTkCore.TTkTerm.inputmouse import TTkMouseEvent
@ -93,9 +95,9 @@ class TTkCheckbox(TTkWidget):
'clicked', 'stateChanged', 'toggled'
)
def __init__(self, *,
text:TTkString='',
text:TTkStringType='',
checked:bool=False,
checkStatus:TTkK.CheckState = None,
checkStatus:Optional[TTkK.CheckState] = None,
tristate:bool=False,
**kwargs) -> None:
'''
@ -115,7 +117,7 @@ class TTkCheckbox(TTkWidget):
self.clicked = pyTTkSignal(bool)
self.toggled = pyTTkSignal(bool)
self._text = TTkString(text)
self._text = text if isinstance(text,TTkString) else TTkString(text)
if checkStatus is not None :
self._checkStatus = checkStatus

104
libs/pyTermTk/TermTk/TTkWidgets/combobox.py

@ -22,6 +22,8 @@
__all__ = ['TTkComboBox']
from typing import Dict,Any,List,Optional
from TermTk.TTkCore.cfg import TTkCfg
from TermTk.TTkCore.constant import TTkK
from TermTk.TTkCore.log import TTkLog
@ -41,7 +43,7 @@ from TermTk.TTkWidgets.resizableframe import TTkResizableFrame
class _TTkComboBoxPopup(TTkResizableFrame):
classStyle = TTkResizableFrame.classStyle
classStyle:Dict[str,Dict[str,Any]] = TTkResizableFrame.classStyle
classStyle['default'] |= {'searchColor': TTkColor.fg("#FFFF00")}
__slots__ = ('_list',
@ -66,13 +68,13 @@ class _TTkComboBoxPopup(TTkResizableFrame):
def paintEvent(self, canvas:TTkCanvas) -> None:
super().paintEvent(canvas)
if text := self._list.search():
if str_text := self._list.search():
w = self.width()-6
color = self.currentStyle()['searchColor']
if len(text) > w:
text = TTkString("",TTkColor.BG_BLUE+TTkColor.FG_CYAN)+TTkString(text[-w+1:],color)
if len(str_text) > w:
text = TTkString("",TTkColor.BG_BLUE+TTkColor.FG_CYAN)+TTkString(str_text[-w+1:],color)
else:
text = TTkString(text,color)
text = TTkString(str_text,color)
canvas.drawText(pos=(1,0), text=f"{text}")
canvas.drawTTkString(pos=(3,0), text=text)
@ -103,24 +105,52 @@ class TTkComboBox(TTkContainer):
__slots__ = ('_list', '_id', '_lineEdit', '_editable', '_insertPolicy', '_textAlign', '_popupFrame',
#signals
'currentIndexChanged', 'currentTextChanged', 'editTextChanged')
currentIndexChanged:pyTTkSignal
'''
This signal is emitted when the index in the combobox changes either through user interaction or programmatically.
:param index: the new current index
:type index: int
'''
currentTextChanged:pyTTkSignal
'''
This signal is emitted when the text of the current item changes. The text is passed as parameter.
:param text: the new current text
:type text: str
'''
editTextChanged:pyTTkSignal
'''
This signal is emitted when the text in the combobox's line edit widget is changed. This signal is only emitted when the combobox is editable.
:param text: the new text in the line edit
:type text: str
'''
_list:List[str]
_popupFrame:Optional[_TTkComboBoxPopup]
def __init__(self, *,
list:list = None,
list:Optional[List[str]] = None,
index:int = -1,
insertPolicy:TTkK.InsertPolicy = TTkK.InsertAtBottom,
textAlign:TTkK.Alignment = TTkK.CENTER_ALIGN,
editable:bool = False,
**kwargs) -> None:
'''
:param list: the list of the items selectable by this combobox, defaults to "[]"
:type list: list(str), optional
:param list: the list of the items selectable by this combobox, defaults to []
:type list: list[str], optional
:param index: the initial selected index, defaults to -1 (no selection)
:type index: int, optional
:param insertPolicy: the policy used to determine where user-inserted items should appear in the combobox, defaults to :py:class:`TTkConstant.InsertPolicy.InsertAtBottom`
:type insertPolicy: :py:class:`TTkConstant.InsertPolicy`, optional
:param insertPolicy: the policy used to determine where user-inserted items should appear in the combobox, defaults to :py:class:`TTkK.InsertPolicy.InsertAtBottom`
:type insertPolicy: :py:class:`TTkK.InsertPolicy`, optional
:param textAlign: This enum type is used to define the text alignment, defaults to :py:class:`TTkConstant.Alignment.CENTER_ALIGN`
:tye textAlign: :py:class:`TTkConstant.Alignment`, optional
:param textAlign: the text alignment for the displayed text, defaults to :py:class:`TTkK.Alignment.CENTER_ALIGN`
:type textAlign: :py:class:`TTkK.Alignment`, optional
:param editable: This property holds whether the combo box can be edited by the user, defaults to False
:param editable: whether the combo box can be edited by the user, defaults to False
:type editable: bool, optional
'''
@ -142,7 +172,7 @@ class TTkComboBox(TTkContainer):
self.setMaximumHeight(1)
def _lineEditChanged(self) -> None:
text = self._lineEdit.text()
text = self._lineEdit.text().toAscii()
self._id=-1
if text in self._list:
self._id = self._list.index(text)
@ -169,9 +199,10 @@ class TTkComboBox(TTkContainer):
self.editTextChanged.emit(text)
def textAlign(self) -> TTkK.Alignment:
'''his property holds the displayed text alignment
'''This property holds the displayed text alignment
:return: :py:class:`TTkConstant.Alignment`
:return: the current text alignment
:rtype: :py:class:`TTkK.Alignment`
'''
return self._textAlign
@ -179,32 +210,32 @@ class TTkComboBox(TTkContainer):
'''This property holds the displayed text alignment
:param align:
:type align: :py:class:`TTkConstant.Alignment`
:type align: :py:class:`TTkK.Alignment`
'''
if self._textAlign != align:
self._textAlign = align
self.update()
def addItem(self, text:TTkString):
def addItem(self, text:str):
'''
Adds an item to the combobox with the given text.
The item is appended to the list of existing items.
:param text:
:type text: :py:class:`TTkString`
:param text: the text of the item to add
:type text: str
'''
self._list.append(text)
self.update()
def addItems(self, items:list[TTkString]) -> None:
def addItems(self, items:list[str]) -> None:
'''
Adds a list of items to the combobox with the given text.
The items are appended to the list of existing items.
:param items:
:type items: list[:py:class:`TTkString`]
:type items: list[str]
'''
for item in items:
self.addItem(item)
@ -217,11 +248,12 @@ class TTkComboBox(TTkContainer):
self._id = -1
self.update()
def lineEdit(self) -> TTkLineEdit:
def lineEdit(self) -> Optional[TTkLineEdit]:
'''
Returns the :py:class:`TTkLineEdit` widget used if the editable flag is enabled
:return: :py:class:`TTkLineEdit`
:return: the line edit if available, None otherwise
:rtype: :py:class:`TTkLineEdit` | None
'''
return self._lineEdit if self._editable else None
@ -247,23 +279,25 @@ class TTkComboBox(TTkContainer):
else:
canvas.drawText(pos=(w-2,0), text="^]", color=borderColor)
def currentText(self) -> TTkString:
def currentText(self) -> str:
'''
Returns the selected text
:return: :py:class:`TTkString`
:return: the current text
:rtype: str
'''
if self._editable:
return self._lineEdit.text()
return self._lineEdit.text().toAscii()
elif self._id >= 0:
return self._list[self._id]
return ""
def currentIndex(self) -> int:
'''
Return the current seleccted index.
Return the current selected index.
:return: int
:return: the current index, -1 if no selection
:rtype: int
'''
return self._id
@ -287,12 +321,12 @@ class TTkComboBox(TTkContainer):
self.update()
@pyTTkSlot(str)
def setCurrentText(self, text:TTkString) -> None:
def setCurrentText(self, text:str) -> None:
'''
Set the selected Text
:param text:
:type text: :py:class:`TTkString`
:type text: str
'''
if self._editable:
self.setEditText(text)
@ -318,7 +352,8 @@ class TTkComboBox(TTkContainer):
'''
Retrieve the insert policy used when a new item is added if the combobox editable flag is true.
:return: :py:class:`TTkK.InsertPolicy`
:return: the current insert policy
:rtype: :py:class:`TTkK.InsertPolicy`
'''
return self._insertPolicy
@ -335,7 +370,8 @@ class TTkComboBox(TTkContainer):
'''
This field holds the editable status of this widget.
:return: bool
:return: True if editable, False otherwise
:rtype: bool
'''
return self._editable
@ -355,7 +391,7 @@ class TTkComboBox(TTkContainer):
self.setFocusPolicy(TTkK.ClickFocus | TTkK.TabFocus)
@pyTTkSlot(str)
def _callback(self, label:TTkString) -> None:
def _callback(self, label:str) -> None:
if self._editable:
self._lineEdit.setText(label)
self.setCurrentIndex(self._list.index(label))

2
libs/pyTermTk/TermTk/TTkWidgets/datetime_time.py

@ -262,7 +262,7 @@ class TTkTime(TTkWidget):
self._state.selected = _FieldSelected.NONE
return True
else:
if '0' <= evt.key <= '9':
if isinstance(evt.key,str) and '0' <= evt.key <= '9':
value = int(evt.key)
secondDigit = self._state.secondDigit
self._state.secondDigit = not secondDigit

10
libs/pyTermTk/TermTk/TTkWidgets/frame.py

@ -22,8 +22,10 @@
__all__ = ['TTkFrame']
from typing import Dict,Any
from TermTk.TTkCore.constant import TTkK
from TermTk.TTkCore.string import TTkString
from TermTk.TTkCore.string import TTkString, TTkStringType
from TermTk.TTkCore.color import TTkColor
from TermTk.TTkWidgets.container import TTkContainer
@ -45,7 +47,7 @@ class TTkFrame(TTkContainer):
Demo2: `splitter.py <https://github.com/ceccopierangiolieugenio/pyTermTk/blob/main/demo/showcase/splitter.py>`_
'''
classStyle = {
classStyle:Dict[str,Dict[str,Any]] = {
'default': {'color': TTkColor.fg("#dddddd")+TTkColor.bg("#222222"),
'fillColor': TTkColor.RST,
'borderColor': TTkColor.RST},
@ -58,7 +60,7 @@ class TTkFrame(TTkContainer):
'_border','_title', '_titleAlign',
'_menubarTop', '_menubarTopPosition', '_menubarBottom', '_menubarBottomPosition')
def __init__(self, *,
title:TTkString='',
title:TTkStringType='',
border:bool=True,
titleAlign:TTkK.Alignment=TTkK.CENTER_ALIGN,
**kwargs) -> None:
@ -72,7 +74,7 @@ class TTkFrame(TTkContainer):
'''
self._titleAlign = titleAlign
self._title = TTkString(title)
self._title = title if isinstance(title,TTkString) else TTkString(title)
self._border = border
self._menubarBottomPosition = 0
self._menubarTop = None

177
libs/pyTermTk/TermTk/TTkWidgets/lineedit.py

@ -22,6 +22,10 @@
__all__ = ['TTkLineEdit']
from enum import IntEnum
from typing import Optional
from TermTk.TTkCore.cfg import TTkCfg
from TermTk.TTkCore.log import TTkLog
from TermTk.TTkCore.constant import TTkK
@ -42,10 +46,53 @@ from TermTk.TTkWidgets.widget import TTkWidget
<--> Offset
'''
class TTkLineEdit(TTkWidget):
'''TTkLineEdit'''
''' TTkLineEdit:
A single-line text editor widget for user input. (`demo <https://ceccopierangiolieugenio.github.io/pyTermTk-Docs/sandbox/sandbox.html?filePath=demo/showcase/lineedit.py>`__)
::
Standard: |Hello World________|
Password: |**********_________|
Number: |123.45_____________|
.. code:: python
import TermTk as ttk
root = ttk.TTk()
class EchoMode(int):
'''EchoMode'''
# Basic text input
edit = ttk.TTkLineEdit(parent=root, pos=(1,1), size=(20,1), text="Hello")
# Password input
password = ttk.TTkLineEdit(parent=root, pos=(1,2), size=(20,1),
echoMode=ttk.TTkLineEdit.EchoMode.Password)
# Numeric input
number = ttk.TTkLineEdit(parent=root, pos=(1,3), size=(20,1),
inputType=ttk.TTkK.InputType.Input_Number)
# Connect to signal
edit.textEdited.connect(lambda text: ttk.TTkLog.debug(f"Edited: {text}"))
root.mainloop()
:param text: Initial text content
:type text: :py:class:`TTkString` or str, optional
:param hint: Placeholder text shown when empty
:type hint: :py:class:`TTkString` or str, optional
:param inputType: Input validation type (TTkK.InputType.Input_Text or TTkK.InputType.Input_Number)
:type inputType: int, optional
:param echoMode: How text is displayed (Normal, NoEcho, Password, PasswordEchoOnEdit)
:type echoMode: :py:class:`EchoMode`, optional
'''
class EchoMode(IntEnum):
''' EchoMode:
Defines how text input is displayed in the line edit.
'''
Normal = 0x00
'''Display characters as they are entered. This is the default.'''
NoEcho = 0x01
@ -73,10 +120,37 @@ class TTkLineEdit(TTkWidget):
'_hint',
# Signals
'returnPressed', 'textChanged', 'textEdited' )
returnPressed:pyTTkSignal
'''
This signal is emitted when the Return or Enter key is pressed.
'''
textChanged:pyTTkSignal
'''
This signal is emitted whenever the text changes programmatically or through user input.
:param text: The new text content
:type text: str
'''
textEdited:pyTTkSignal
'''
This signal is emitted whenever the text is edited by the user (not programmatically).
:param text: The edited text content
:type text: str
'''
_text:TTkString
_hint:TTkString
_cursorPos:int
_inputType:TTkK.InputType
def __init__(self, *,
text:TTkString='',
hint:TTkString='',
inputType:int=TTkK.Input_Text,
text:TTkStringType='',
hint:TTkStringType='',
inputType:TTkK.InputType=TTkK.InputType.Input_Text,
echoMode:EchoMode=EchoMode.Normal,
**kwargs) -> None:
# Signals
@ -88,8 +162,8 @@ class TTkLineEdit(TTkWidget):
self._selectionFrom = 0
self._selectionTo = 0
self._replace=False
self._text = TTkString(text)
self._hint = TTkString(hint)
self._text = text if isinstance(text,TTkString) else TTkString(text)
self._hint = hint if isinstance(hint,TTkString) else TTkString(hint)
self._inputType = inputType
self._echoMode = echoMode
self._clipboard = TTkClipboard()
@ -101,8 +175,14 @@ class TTkLineEdit(TTkWidget):
self.enableWidgetCursor()
@pyTTkSlot(TTkStringType)
def setText(self, text:TTkStringType, cursorPos=0x1000):
'''setText'''
def setText(self, text:TTkStringType, cursorPos:int=0x1000) -> None:
''' Set the text content of the line edit
:param text: The new text to display
:type text: :py:class:`TTkString` or str
:param cursorPos: Position to place the cursor (defaults to end of text)
:type cursorPos: int, optional
'''
if text != self._text:
self.textChanged.emit(text)
self._text = TTkString(text)
@ -110,35 +190,59 @@ class TTkLineEdit(TTkWidget):
self._cursorPos = max(0,min(cursorPos, len(text)))
self._pushCursor()
def text(self):
'''text'''
def text(self) -> TTkString:
''' Get the current text content
:return: The current text
:rtype: :py:class:`TTkString`
'''
return self._text
def inputType(self):
'''inputType'''
def inputType(self) -> TTkK.InputType:
''' Get the current input validation type
:return: The input type (:py:class:`TTkK.InputType.Input_Text` or :py:class:`TTkK.InputType.Input_Number`)
:rtype: :py:class:`TTkK.InputType`
'''
return self._inputType
def setInputType(self, inputType):
'''inputType'''
if bool(inputType & TTkK.Input_Text) and bool(inputType & TTkK.Input_Number):
def setInputType(self, inputType:TTkK.InputType) -> None:
''' Set the input validation type
When set to Input_Number, only numeric values (including decimals) are accepted.
:param inputType: The input type to validate against
:type inputType: :py:class:`TTkK.InputType`
'''
if bool(inputType & TTkK.InputType.Input_Text) and bool(inputType & TTkK.InputType.Input_Number):
return
# Kept here for retrocompatibility
if inputType & TTkK.Input_Password:
TTkLog.warn("TTkK.Input_Password is deprecated, use the EchoMode instead")
if inputType & TTkK.InputType.Input_Password:
TTkLog.warn("TTkK.InputType.Input_Password is deprecated, use the EchoMode instead")
self._echoMode = TTkLineEdit.EchoMode.Password
inputType &= ~TTkK.Input_Password
if inputType & ~(TTkK.Input_Text|TTkK.Input_Number):
inputType &= ~TTkK.InputType.Input_Password
if inputType & ~(TTkK.InputType.Input_Text|TTkK.InputType.Input_Number):
return
self._inputType = inputType & (TTkK.Input_Text|TTkK.Input_Number) if inputType else TTkK.Input_Text
if ( self._inputType == TTkK.Input_Number and
self._inputType = inputType & (TTkK.InputType.Input_Text|TTkK.InputType.Input_Number) if inputType else TTkK.InputType.Input_Text
if ( self._inputType == TTkK.InputType.Input_Number and
not self._isFloat(self._text)):
self._text = TTkString('0')
self.update()
def echoMode(self) -> EchoMode:
''' Get the current echo mode
:return: The current echo mode
:rtype: :py:class:`EchoMode`
'''
return self._echoMode
def setEchoMode(self, echoMode:EchoMode):
''' Set how text is displayed
:param echoMode: The echo mode (Normal, NoEcho, Password, PasswordEchoOnEdit)
:type echoMode: :py:class:`EchoMode`
'''
self._echoMode = echoMode
self.update()
@ -229,12 +333,16 @@ class TTkLineEdit(TTkWidget):
@pyTTkSlot()
def copy(self):
''' Copy the selected text to the clipboard
'''
if self._selectionFrom >= self._selectionTo: return
txt = self._text.substring(fr=self._selectionFrom,to=self._selectionTo)
self._clipboard.setText(txt)
@pyTTkSlot()
def cut(self):
''' Cut the selected text to the clipboard
'''
self.copy()
self._text = self._text.substring(to=self._selectionFrom) + self._text.substring(fr=self._selectionTo)
self._cursorPos = self._selectionFrom
@ -242,11 +350,20 @@ class TTkLineEdit(TTkWidget):
@pyTTkSlot()
def paste(self):
''' Paste text from the clipboard at the cursor position
'''
txt = self._clipboard.text()
self.pasteEvent(txt)
def pasteEvent(self, txt:str):
txt = TTkString().join(txt.split('\n'))
''' Handle paste event with custom text
:param txt: The text to paste
:type txt: str
:return: True if the event was handled
:rtype: bool
'''
ttk_txt = TTkString(''.join(txt.split('\n')))
text = self._text
@ -261,11 +378,11 @@ class TTkLineEdit(TTkWidget):
else:
post = text.substring(fr=self._cursorPos)
text = pre + txt + post
if ( self._inputType & TTkK.Input_Number and
text = pre + ttk_txt + post
if ( self._inputType & TTkK.InputType.Input_Number and
not self._isFloat(text) ):
return True
self.setText(text, self._cursorPos+txt.termWidth())
self.setText(text, self._cursorPos+ttk_txt.termWidth())
self._pushCursor()
self.textEdited.emit(self._text)
@ -323,7 +440,7 @@ class TTkLineEdit(TTkWidget):
text = self._text.substring(to=prev) + self._text.substring(fr=self._cursorPos)
cursorPos = prev
if ( self._inputType & TTkK.Input_Number and
if ( self._inputType & TTkK.InputType.Input_Number and
not self._isFloat(self._text) ):
self.setText('0', 1)
else:
@ -333,7 +450,7 @@ class TTkLineEdit(TTkWidget):
if evt.key == TTkK.Key_Enter:
self.returnPressed.emit()
else:
elif isinstance(evt.key,str):
text = self._text
if self._selectionFrom < self._selectionTo:
@ -348,7 +465,7 @@ class TTkLineEdit(TTkWidget):
post = text.substring(fr=self._cursorPos)
text = pre + evt.key + post
if ( self._inputType & TTkK.Input_Number and
if ( self._inputType & TTkK.InputType.Input_Number and
( evt.key in (' ') or not self._isFloat(text) )):
return True
self.setText(text, self._cursorPos+1)

8
tests/t.ui/test.ui.009.widgets.form.py

@ -67,14 +67,14 @@ row += 1; win_form1_grid_layout.addWidget(ttk.TTkLabel(text='Line Edit Test 5'),
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='Line Edit Test 5'),row,2)
row += 1; win_form1_grid_layout.addWidget(ttk.TTkLabel(text='Line Edit Input Number'),row,0)
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='123456', inputType=ttk.TTkK.Input_Number),row,2)
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='123456', inputType=ttk.TTkK.InputType.Input_Number),row,2)
row += 1; win_form1_grid_layout.addWidget(ttk.TTkLabel(text='Line Edit Input Wrong Number'),row,0)
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='No num Text', inputType=ttk.TTkK.Input_Number),row,2)
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='No num Text', inputType=ttk.TTkK.InputType.Input_Number),row,2)
row += 1; win_form1_grid_layout.addWidget(ttk.TTkLabel(text='Line Edit Input Password'),row,0)
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='Password', inputType=ttk.TTkK.Input_Password),row,2)
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='Password', inputType=ttk.TTkK.InputType.Input_Password),row,2)
row += 1; win_form1_grid_layout.addWidget(ttk.TTkLabel(text='Line Edit Number Password'),row,0)
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='Password', inputType=ttk.TTkK.Input_Password+ttk.TTkK.Input_Number),row,2)
win_form1_grid_layout.addWidget(ttk.TTkLineEdit(text='Password', inputType=ttk.TTkK.InputType.Input_Password|ttk.TTkK.InputType.Input_Number),row,2)
row += 1; win_form1_grid_layout.addWidget(ttk.TTkLabel(text='Checkbox'),row,0)
win_form1_grid_layout.addWidget(ttk.TTkCheckbox(),row,2)

11
tools/check.import.sh

@ -4,6 +4,7 @@ __check(){
grep -r -e "^import" -e "^from" libs/pyTermTk/TermTk |
grep -v -e "from TermTk" -e "import TermTk" |
grep -v "from typing import" |
grep -v "from enum import" |
grep -v "__init__.py:from \.[^ ]* *import" |
grep -v -e "import re" -e "import os" -e "import datetime" |
grep -v \
@ -46,9 +47,7 @@ __check(){
-e "propertyanimation.py:import time, math" \
-e "savetools.py:import importlib.util" \
-e "savetools.py:import json" \
-e "TTkCore/constant.py:from enum import IntEnum" |
grep -v \
-e "TTkTerm/term_base.py:from enum import Flag" \
-e "TTkTerm/input_mono.py:from time import time" \
-e "TTkTerm/input_mono.py:import platform" \
-e "TTkTerm/input_mono.py:from ..drivers import TTkInputDriver" \
@ -58,7 +57,6 @@ __check(){
-e "TTkTerm/input.py:from .input_thread import *" |
grep -v \
-e "TTkGui/__init__.py:import importlib.util" \
-e "TTkGui/textcursor.py:from enum import IntEnum" \
-e "TTkGui/textdocument.py:from threading import Lock" \
-e "TTkGui/textdocument_highlight_pygments.py:from pygments" |
grep -v \
@ -116,19 +114,12 @@ __check(){
-e "TTkTerminal/__init__.py:import platform" |
grep -v \
-e "TTkWidgets/widget.py:from __future__ import annotations" \
-e "TTkWidgets/tabwidget.py:from enum import Enum" \
-e "TTkWidgets/apptemplate.py:from enum import IntEnum" \
-e "TTkModelView/__init__.py:from importlib.util import find_spec" \
-e "TTkModelView/table_edit_proxy.py:from enum import Enum, auto" \
-e "TTkModelView/tablemodelcsv.py:import csv" \
-e "TTkModelView/tablemodelsqlite3.py:import sqlite3" \
-e "TTkModelView/tablemodelsqlite3.py:import threading" |
grep -v \
-e "TTkWidgets/datetime_date.py:from enum import IntEnum,auto" \
-e "TTkWidgets/datetime_date.py:import calendar" \
-e "TTkWidgets/datetime_time.py:from enum import IntEnum,auto" \
-e "TTkWidgets/datetime_datetime.py:from enum import IntEnum,auto" \
-e "TTkWidgets/datetime_date_form.py:from enum import IntEnum,auto" \
-e "TTkWidgets/datetime_date_form.py:import calendar"
} ;

Loading…
Cancel
Save