Skip to content

Commit

Permalink
Merge pull request #160 from ceccopierangiolieugenio/dev
Browse files Browse the repository at this point in the history
Current Dev Branch
  • Loading branch information
ceccopierangiolieugenio committed Oct 3, 2023
2 parents f9c2a4d + c56ef8d commit 52ec550
Show file tree
Hide file tree
Showing 179 changed files with 4,007 additions and 1,545 deletions.
6 changes: 3 additions & 3 deletions TermTk/TTkAbstract/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from .abstractscrollview import TTkAbstractScrollViewInterface, TTkAbstractScrollView, TTkAbstractScrollViewGridLayout
from .abstractscrollarea import TTkAbstractScrollArea
from .abstractitemmodel import TTkAbstractItemModel
from .abstractscrollview import *
from .abstractscrollarea import *
from .abstractitemmodel import *
4 changes: 2 additions & 2 deletions TermTk/TTkAbstract/abstractitemmodel.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#!/usr/bin/env python3

# MIT License
#
# Copyright (c) 2021 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
Expand All @@ -22,6 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

__all__ = ['TTkAbstractItemModel']

from TermTk.TTkCore.signal import pyTTkSignal

class TTkAbstractItemModel():
Expand Down
12 changes: 10 additions & 2 deletions TermTk/TTkAbstract/abstractscrollarea.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,18 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

__all__ = ['TTkAbstractScrollArea']

from TermTk.TTkCore.constant import TTkK
# from TermTk.TTkCore.log import TTkLog
from TermTk.TTkCore.signal import pyTTkSlot
from TermTk.TTkWidgets.widget import TTkWidget
from TermTk.TTkWidgets.container import TTkContainer
from TermTk.TTkWidgets.scrollbar import TTkScrollBar
from TermTk.TTkLayouts.gridlayout import TTkGridLayout
from TermTk.TTkAbstract.abstractscrollview import TTkAbstractScrollViewInterface

class TTkAbstractScrollArea(TTkWidget):
class TTkAbstractScrollArea(TTkContainer):
__slots__ = (
'_processing', # this flag is required to avoid unnecessary loop on edge cases
'_viewport',
Expand Down Expand Up @@ -123,7 +126,12 @@ def setViewport(self, viewport):
raise TypeError("TTkAbstractScrollViewInterface is required in TTkAbstractScrollArea.setVewport(viewport)")
if self._viewport:
self._viewport.viewChanged.disconnect(self._viewportChanged)
self.layout().removeWidget(self._viewport)
# TODO: Remove this check once
# unified "addWidget" and "addItem" in the TTKGridLayout
if isinstance(viewport, TTkWidget):
self.layout().removeWidget(self._viewport)
else:
self.layout().removeItem(self._viewport)
self._viewport = viewport
self._viewport.viewChanged.connect(self._viewportChanged)
self._verticalScrollBar.sliderMoved.connect(self._vscrollMoved)
Expand Down
45 changes: 39 additions & 6 deletions TermTk/TTkAbstract/abstractscrollview.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#!/usr/bin/env python3

# MIT License
#
# Copyright (c) 2021 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
Expand All @@ -22,10 +20,13 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

__all__ = ['TTkAbstractScrollViewInterface', 'TTkAbstractScrollView', 'TTkAbstractScrollViewGridLayout']

from TermTk.TTkCore.constant import TTkK
from TermTk.TTkCore.cfg import TTkCfg
from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal
from TermTk.TTkWidgets.widget import TTkWidget
from TermTk.TTkWidgets.container import TTkContainer
from TermTk.TTkLayouts.layout import TTkLayout
from TermTk.TTkLayouts.gridlayout import TTkGridLayout

class TTkAbstractScrollViewInterface():
Expand All @@ -44,7 +45,7 @@ def viewMoveTo(self, x: int, y: int):
def getViewOffsets(self):
return self._viewOffsetX, self._viewOffsetY

class TTkAbstractScrollView(TTkWidget, TTkAbstractScrollViewInterface):
class TTkAbstractScrollView(TTkContainer, TTkAbstractScrollViewInterface):
__slots__ = (
'_viewOffsetX', '_viewOffsetY',
# Signals
Expand All @@ -55,9 +56,9 @@ def __init__(self, *args, **kwargs):
self.viewMovedTo = pyTTkSignal(int, int) # x, y
self.viewSizeChanged = pyTTkSignal(int, int) # w, h
self.viewChanged = pyTTkSignal()
TTkWidget.__init__(self, *args, **kwargs)
self._viewOffsetX = 0
self._viewOffsetY = 0
TTkContainer.__init__(self, *args, **kwargs)

@pyTTkSlot(int, int)
def viewMoveTo(self, x: int, y: int):
Expand Down Expand Up @@ -96,6 +97,38 @@ def update(self, repaint=True, updateLayout=False, updateParent=False):
self.viewChanged.emit()
return super().update(repaint, updateLayout, updateParent)

class TTkAbstractScrollViewLayout(TTkLayout, TTkAbstractScrollViewInterface):
__slots__ = (
'_viewOffsetX', '_viewOffsetY',
# Signals
'viewMovedTo', 'viewSizeChanged', 'viewChanged', '_excludeEvent')

def __init__(self, *args, **kwargs):
# Signals
self.viewMovedTo = pyTTkSignal(int, int) # x, y
self.viewSizeChanged = pyTTkSignal(int, int) # w, h
self.viewChanged = pyTTkSignal()
self._viewOffsetX = 0
self._viewOffsetY = 0
self._excludeEvent = False
TTkLayout.__init__(self, *args, **kwargs)

def viewFullAreaSize(self) -> (int, int):
_,_,w,h = self.fullWidgetAreaGeometry()
return w,h

def viewDisplayedSize(self) -> (int, int):
_,_,w,h = self.geometry()
return w,h

@pyTTkSlot(int, int)
def viewMoveTo(self, x: int, y: int):
self.setOffset(-x,-y)

def setGeometry(self, x, y, w, h):
TTkLayout.setGeometry(self, x, y, w, h)
self.viewChanged.emit()

class TTkAbstractScrollViewGridLayout(TTkGridLayout, TTkAbstractScrollViewInterface):
__slots__ = (
'_viewOffsetX', '_viewOffsetY',
Expand All @@ -107,10 +140,10 @@ def __init__(self, *args, **kwargs):
self.viewMovedTo = pyTTkSignal(int, int) # x, y
self.viewSizeChanged = pyTTkSignal(int, int) # w, h
self.viewChanged = pyTTkSignal()
TTkGridLayout.__init__(self, *args, **kwargs)
self._viewOffsetX = 0
self._viewOffsetY = 0
self._excludeEvent = False
TTkGridLayout.__init__(self, *args, **kwargs)

@pyTTkSlot(int, int)
def viewMoveTo(self, x: int, y: int):
Expand Down
10 changes: 5 additions & 5 deletions TermTk/TTkCore/TTkTerm/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .inputkey import TTkKeyEvent
from .inputmouse import TTkMouseEvent
from .colors import TTkTermColor
from .term import TTkTerm
from .input import TTkInput
from .inputkey import *
from .inputmouse import *
from .colors import *
from .term import *
from .input import *
60 changes: 44 additions & 16 deletions TermTk/TTkCore/TTkTerm/colors.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#!/usr/bin/env python3

# MIT License
#
# Copyright (c) 2022 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
Expand All @@ -22,6 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

__all__ = ['TTkTermColor']

# Ansi Escape Codes:
# https://conemu.github.io/en/AnsiEscapeCodes.html

Expand All @@ -30,14 +30,38 @@
from .colors_ansi_map import ansiMap256, ansiMap16

class TTkTermColor():
BOLD = 0x01
ITALIC = 0x02
UNDERLINE = 0x04
STRIKETROUGH = 0x08
BLINKING = 0x10
BOLD = 0x01 # <ESC>[1m
FAINT = 0x02 # <ESC>[2m
ITALIC = 0x04 # <ESC>[3m
UNDERLINE = 0x08 # <ESC>[4m
BLINKING = 0x10 # <ESC>[5m
REVERSED = 0x20 # <ESC>[7m
HIDDEN = 0x40 # <ESC>[8m
STRIKETROUGH = 0x80 # <ESC>[9m

SGR_SET = { # CSI Pm m Character Attributes (SGR).
# Ps = 0 ⇒ Normal (default), VT100.
1: BOLD , # Ps = 1 ⇒ Bold, VT100.
2: FAINT , # Ps = 2 ⇒ Faint, decreased intensity, ECMA-48 2nd.
3: ITALIC , # Ps = 3 ⇒ Italicized, ECMA-48 2nd.
4: UNDERLINE , # Ps = 4 ⇒ Underlined, VT100.
5: BLINKING , # Ps = 5 ⇒ Blink, VT100. - This appears as Bold in X11R6 xterm.
7: REVERSED , # Ps = 7 ⇒ Inverse, VT100.
8: HIDDEN , # Ps = 8 ⇒ Invisible, i.e., hidden, ECMA-48 2nd, VT300.
9: STRIKETROUGH } # Ps = 9 ⇒ Crossed-out characters, ECMA-48 3rd.

SGR_RST = { # CSI Pm m Character Attributes (SGR).
# Ps = 2 1 ⇒ Doubly-underlined, ECMA-48 3rd.
22: ~(BOLD|FAINT), # Ps = 2 2 ⇒ Normal (neither bold nor faint), ECMA-48 3rd.
23: ~ITALIC, # Ps = 2 3 ⇒ Not italicized, ECMA-48 3rd.
24: ~UNDERLINE, # Ps = 2 4 ⇒ Not underlined, ECMA-48 3rd.
25: ~BLINKING, # Ps = 2 5 ⇒ Steady (not blinking), ECMA-48 3rd.
27: ~REVERSED, # Ps = 2 7 ⇒ Positive (not inverse), ECMA-48 3rd.
28: ~HIDDEN, # Ps = 2 8 ⇒ Visible, i.e., not hidden, ECMA-48 3rd, VT300.
29: ~STRIKETROUGH } # Ps = 2 9 ⇒ Not crossed-out, ECMA-48 3rd.

@staticmethod
def rgb2ansi(fg: tuple=None, bg:tuple=None, mod:int=0, clean:bool=False):
def rgb2ansi(fg: tuple=None, bg:tuple=None, mod:int=0, link:str='', clean:bool=False):
ret = []

if clean:
Expand All @@ -50,15 +74,20 @@ def rgb2ansi(fg: tuple=None, bg:tuple=None, mod:int=0, clean:bool=False):

if mod & TTkTermColor.BOLD:
ret.append('1')
if mod & TTkTermColor.FAINT:
ret.append('2')
if mod & TTkTermColor.ITALIC:
ret.append('3')
if mod & TTkTermColor.UNDERLINE:
ret.append('4')
if mod & TTkTermColor.STRIKETROUGH:
ret.append('9')
if mod & TTkTermColor.BLINKING:
ret.append('5')

if mod & TTkTermColor.REVERSED:
ret.append('7')
if mod & TTkTermColor.HIDDEN:
ret.append('8')
if mod & TTkTermColor.STRIKETROUGH:
ret.append('9')
if ret:
return f'\033[{";".join(str(x) for x in ret)}m'
else:
Expand Down Expand Up @@ -108,11 +137,10 @@ def ansi2rgb(ansi:str):
bg = None
mod = 0
clean = True
elif s==1: mod += TTkTermColor.BOLD
elif s==3: mod += TTkTermColor.ITALIC
elif s==4: mod += TTkTermColor.UNDERLINE
elif s==9: mod += TTkTermColor.STRIKETROUGH
elif s==5: mod += TTkTermColor.BLINKING
elif _sgr:=TTkTermColor.SGR_SET.get(s,None):
mod |= _sgr
elif _sgr:=TTkTermColor.SGR_RST.get(s,None):
mod &= _sgr
return fg,bg,mod,clean


Expand Down
2 changes: 0 additions & 2 deletions TermTk/TTkCore/TTkTerm/colors_ansi_map.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#!/usr/bin/env python3

# MIT License
#
# Copyright (c) 2022 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
Expand Down
36 changes: 29 additions & 7 deletions TermTk/TTkCore/TTkTerm/input.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#!/usr/bin/env python3

# MIT License
#
# Copyright (c) 2021 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
Expand All @@ -22,6 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

__all__ = ['TTkInput']

import re
from time import time

Expand All @@ -46,12 +46,16 @@ class TTkInput:
'_readInput',
'_leftLastTime', '_midLastTime', '_rightLastTime',
'_leftTap', '_midTap', '_rightTap',
'_pasteBuffer', '_bracketedPaste',
# Signals
'inputEvent'
'inputEvent', 'pasteEvent'
)

def __init__(self):
self.inputEvent = pyTTkSignal(TTkKeyEvent, TTkMouseEvent)
self.pasteEvent = pyTTkSignal(str)
self._pasteBuffer = ""
self._bracketedPaste = False
self._readInput = None
self._leftLastTime = 0
self._midLastTime = 0
Expand Down Expand Up @@ -79,7 +83,20 @@ def start(self):

mouse_re = re.compile(r"\033\[<(\d+);(\d+);(\d+)([mM])")
def key_process(self, stdinRead):
if self._bracketedPaste:
if stdinRead.endswith("\033[201~"):
self._pasteBuffer += stdinRead[:-6]
self._bracketedPaste = False
# due to the CRNL methos (don't ask me why) the terminal
# is substituting all the \n with \r
self.pasteEvent.emit(self._pasteBuffer.replace('\r','\n'))
self._pasteBuffer = ""
else:
self._pasteBuffer += stdinRead
return

mevt,kevt = None, None

if not stdinRead.startswith("\033[<"):
# Key Event
kevt = TTkKeyEvent.parse(stdinRead)
Expand Down Expand Up @@ -153,12 +170,17 @@ def _checkTap(lastTime, tap):
evt = TTkMouseEvent.Move

mevt = TTkMouseEvent(x, y, key, evt, mod, tap, m.group(0).replace("\033", "<ESC>"))
if kevt or mevt:
self.inputEvent.emit(kevt, mevt)
return

if kevt is None and mevt is None:
hex = [f"0x{ord(x):02x}" for x in stdinRead]
TTkLog.error("UNHANDLED: "+stdinRead.replace("\033","<ESC>") + " - "+",".join(hex))
if stdinRead.startswith("\033[200~"):
self._pasteBuffer = stdinRead[6:]
self._bracketedPaste = True
return

self.inputEvent.emit(kevt, mevt)
hex = [f"0x{ord(x):02x}" for x in stdinRead]
TTkLog.error("UNHANDLED: "+stdinRead.replace("\033","<ESC>") + " - "+",".join(hex))


def main():
Expand Down
4 changes: 2 additions & 2 deletions TermTk/TTkCore/TTkTerm/inputkey.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#!/usr/bin/env python3

# MIT License
#
# Copyright (c) 2021 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
Expand All @@ -22,6 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

__all__ = ['TTkKeyEvent']

from TermTk.TTkCore.constant import TTkK

class TTkKeyEvent:
Expand Down
4 changes: 2 additions & 2 deletions TermTk/TTkCore/TTkTerm/inputmouse.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#!/usr/bin/env python3

# MIT License
#
# Copyright (c) 2021 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
Expand All @@ -22,6 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

__all__ = ['TTkMouseEvent']

from TermTk.TTkCore.constant import TTkK

class TTkMouseEvent:
Expand Down
5 changes: 3 additions & 2 deletions TermTk/TTkCore/TTkTerm/readinputlinux.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#!/usr/bin/env python3

# MIT License
#
# Copyright (c) 2022 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
Expand Down Expand Up @@ -57,6 +55,9 @@ def read(self):

# Split all the ansi sequences
# or yield any separate input char
if stdinRead == '\033':
yield '\033'
continue
for sr in rm.findall(stdinRead):
if '\033' == sr[0]:
yield sr
Expand Down
2 changes: 0 additions & 2 deletions TermTk/TTkCore/TTkTerm/readinputlinux_thread.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#!/usr/bin/env python3

# MIT License
#
# Copyright (c) 2022 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
Expand Down
Loading

0 comments on commit 52ec550

Please sign in to comment.