Browse Source

refactor: adapted ttkode to the latest pyTermTk

pull/384/head
Parodi, Eugenio 🌶 12 months ago
parent
commit
542ecd7f77
  1. 35
      apps/tlogg/Makefile
  2. 5
      apps/ttkode/ttkode/__init__.py
  3. 2
      apps/ttkode/ttkode/app/__init__.py
  4. 6
      apps/ttkode/ttkode/app/about.py
  5. 2
      apps/ttkode/ttkode/app/cfg.py
  6. 142
      apps/ttkode/ttkode/app/kodeformatter.py
  7. 165
      apps/ttkode/ttkode/app/kodetextdocument.py
  8. 31
      apps/ttkode/ttkode/app/kodetextedit.py
  9. 103
      apps/ttkode/ttkode/app/main.py
  10. 2
      apps/ttkode/ttkode/app/options.py
  11. 119
      apps/ttkode/ttkode/app/ttkode.py
  12. 4
      libs/pyTermTk/TermTk/TTkWidgets/about.py

35
apps/tlogg/Makefile

@ -1,35 +0,0 @@
.PHONY: doc runGittk runDemo build deploy buildTest deployTest
.venv:
python3 -m venv .venv
. .venv/bin/activate ; \
pip install -r docs/requirements.txt
# Regen requirements;
# pip freeze > docs/requirements.txt
build: .venv
. .venv/bin/activate ; \
rm -rf dist ; \
tools/prepareBuild.sh release ; \
cd tmp ; \
python3 -m build
buildTest: .venv
. .venv/bin/activate ; \
rm -rf dist ; \
tools/prepareBuild.sh test ; \
cd tmp ; \
python3 -m build ;
deployTest: .venv
. .venv/bin/activate ; \
python3 -m twine upload --repository testpypi tmp/dist/* --verbose
deploy: .venv
. .venv/bin/activate ; \
python3 -m twine upload tmp/dist/* --repository tlogg --verbose
#test: .venv
# . .venv/bin/activate ; \
# flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics --exclude .venv,build,tmp ; \
# pytest demo/demo.py

5
apps/ttkode/ttkode/__init__.py

@ -23,8 +23,3 @@
# SOFTWARE.
__version__:str = '0.2.15-a.2'
from .app import *
if __name__ == "__main__":
main()

2
apps/ttkode/ttkode/app/__init__.py

@ -25,5 +25,5 @@
from .cfg import *
# from .glbl import *
from .ttkode import *
from .main import *
from .kodetextdocument import KodeTextDocument

6
apps/ttkode/ttkode/app/about.py

@ -1,5 +1,3 @@
#!/usr/bin/env python3
# MIT License
#
# Copyright (c) 2021 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
@ -22,6 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
__all__ = ['About']
from TermTk.TTkCore.log import TTkLog
from TermTk.TTkCore.color import TTkColor
from TermTk import TTkAbout, TTkWindow
@ -47,6 +47,8 @@ class About(TTkAbout):
def paintEvent(self, canvas):
c = [0xFF,0xFF,0xFF]
for i,line in enumerate(TTkAbout._peppered_string.split('\n')):
canvas.drawTTkString(pos=(1,3+i), text=line)
for y, line in enumerate(About.ttkode):
canvas.drawText(pos=(13,3+y),text=line, color=TTkColor.fg(f'#{c[0]:02X}{c[1]:02X}{c[2]:02X}'))
c[2]-=0x18

2
apps/ttkode/ttkode/app/cfg.py

@ -22,6 +22,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
__all__ = ['TTKodeCfg']
import os
import json

142
apps/ttkode/ttkode/app/kodeformatter.py

@ -1,142 +0,0 @@
# MIT License
#
# Copyright (c) 2022 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.
from pygments.formatter import Formatter
from pygments.token import Keyword, Name, Comment, String, Error, \
Number, Operator, Generic, Token, Whitespace
from TermTk import TTkString, TTkColor, TTkLog
#: Map token types to a tuple of color values for light and dark
#: backgrounds.
TTKODE_COLORS = {
Token: TTkColor.RST, # ('', ''),
Whitespace: TTkColor.fg('#888888') , # ('gray', 'brightblack'),
Comment: TTkColor.fg('#888888') , # ('gray', 'brightblack'),
Comment.Preproc: TTkColor.fg('#00FFFF') , # ('cyan', 'brightcyan'),
Keyword: TTkColor.fg('#0000FF') , # ('blue', 'brightblue'),
Keyword.Type: TTkColor.fg('#00FFFF') , # ('cyan', 'brightcyan'),
Operator.Word: TTkColor.fg('#FF8800') , # ('magenta', 'brightmagenta'),
Name.Builtin: TTkColor.fg('#00FFFF') , # ('cyan', 'brightcyan'),
Name.Function: TTkColor.fg('#00FF00') , # ('green', 'brightgreen'),
Name.Namespace: TTkColor.fg('#00FFFF') , # ('_cyan_', '_brightcyan_'),
Name.Class: TTkColor.fg('#00FF00') , # ('_green_', '_brightgreen_'),
Name.Exception: TTkColor.fg('#00FFFF') , # ('cyan', 'brightcyan'),
Name.Decorator: TTkColor.fg('#888888') , # ('brightblack', 'gray'),
Name.Variable: TTkColor.fg('#888888') , # ('red', 'brightred'),
Name.Constant: TTkColor.fg('#888888') , # ('red', 'brightred'),
Name.Attribute: TTkColor.fg('#00FFFF') , # ('cyan', 'brightcyan'),
Name.Tag: TTkColor.fg('#0000FF') , # ('brightblue', 'brightblue'),
String: TTkColor.fg('#FFFF00') , # ('yellow', 'yellow'),
Number: TTkColor.fg('#0000FF') , # ('blue', 'brightblue'),
Generic.Deleted: TTkColor.fg('#FF0000') , # ('brightred', 'brightred'),
Generic.Inserted: TTkColor.fg('#00FF00') , # ('green', 'brightgreen'),
Generic.Heading: TTkColor.fg('#888888') , # ('**', '**'),
Generic.Subheading: TTkColor.fg('#FF8800') , # ('*magenta*', '*brightmagenta*'),
Generic.Prompt: TTkColor.fg('#888888') , # ('**', '**'),
Generic.Error: TTkColor.fg('#FF0000') , # ('brightred', 'brightred'),
Error: TTkColor.fg('#FF0000') , # ('_brightred_', '_brightred_'),
}
class KodeFormatter(Formatter):
class Data():
__slots__=('lines', 'block', 'error', 'multiline')
def __init__(self, lines, block):
self.lines = lines
self.block = block
self.error = None
self.multiline = False
__slots__ = ('_dl', '_blockNum', '_kodeStyles')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._kodeStyles = {}
self._blockNum = 1
for token, style in self.style:
# Token = Token.Comment.PreprocFile
# style = {
# 'color': '6272a4',
# 'bgcolor': None,
# 'bold': False, 'italic': False, 'underline': False,
# 'border': None,
# 'roman': None, 'sans': None, 'mono': None,
# 'ansicolor': None, 'bgansicolor': None}
# TTkLog.debug(f"{token=} {style=}")
color = TTkColor.RST
if style['color']:
color += TTkColor.fg(f"#{style['color']}")
if style['bgcolor']:
color += TTkColor.bg(f"#{style['bgcolor']}")
if style['bold']:
color += TTkColor.BOLD
if style['italic']:
color += TTkColor.ITALIC
if style['underline']:
color += TTkColor.UNDERLINE
self._kodeStyles[token] = color
super().__init__()
def setDl(self,dl):
self._dl = dl
def format(self, tokensource, _):
multiline = False
multilineId = 0
for ttype, value in tokensource:
if ttype == Error and self._dl.error is None:
self._dl.error = len(self._dl.lines)-1
# self._dl.multiline = ttype == Comment.Multiline
multiline = ttype == Comment.Multiline
while ttype not in self._kodeStyles:
ttype = ttype.parent
# TTkLog.debug (f"{ttype=}")
# TTkLog.debug (f"{value=}")
color = self._kodeStyles[ttype]
values = value.split('\n')
self._dl.lines[-1] += TTkString(values[0],color)
self._dl.lines += [TTkString(t,color) for t in values[1:]]
self._dl.block[-1] = self._blockNum
self._dl.block += [self._blockNum]*(len(values)-1)
# self._dl.lines += [TTkString(t) for t in value.split('\n')]
# multiline = len(values)>1 if self._dl.lines[-1]._text == values[-1] else self._dl.multiline
# if self._dl.lines[-1]._text == '' or not multiline:
# self._blockNum += 1
# multilineId = len(self._dl.lines)
if multiline:
multilineId += len(values)
else:
multilineId = 0
self._blockNum += 1
if multiline:
self._dl.multiline = multilineId

165
apps/ttkode/ttkode/app/kodetextdocument.py

@ -1,165 +0,0 @@
# MIT License
#
# Copyright (c) 2022 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.
from threading import Lock
from pygments import highlight
from pygments.util import ClassNotFound
from pygments.lexers import guess_lexer, guess_lexer_for_filename, special
from pygments.formatters import TerminalFormatter, Terminal256Formatter, TerminalTrueColorFormatter
from TermTk import TTk, TTkK, TTkLog, TTkCfg, TTkTheme, TTkTerm, TTkHelper, TTkTimer
from TermTk import TTkString
from TermTk import TTkColor, TTkColorGradient
from TermTk import pyTTkSlot, pyTTkSignal
from TermTk import TTkTextDocument
from .kodeformatter import KodeFormatter
class KodeTextDocument(TTkTextDocument):
_linesRefreshed = 30
__slots__ = (
'_filePath', '_timerRefresh',
'kodeHighlightUpdate', '_kodeDocMutex',
'_blocks', '_changedContent', '_refreshContent',
'_lexer', '_formatter')
def __init__(self, filePath:str="", **kwargs):
self.kodeHighlightUpdate = pyTTkSignal()
self._kodeDocMutex = Lock()
self._lexer = None
self._blocks = []
# self._formatter = KodeFormatter(style='dracula')
self._filePath = filePath
self._formatter = KodeFormatter(style='gruvbox-dark')
self._timerRefresh = TTkTimer()
super().__init__(**kwargs)
self._changedContent = (0,0,len(self._dataLines))
self._refreshContent = (0,KodeTextDocument._linesRefreshed)
self._timerRefresh.timeout.connect(self._refreshEvent)
self._timerRefresh.start(0.3)
self.contentsChange.connect(lambda a,b,c: TTkLog.debug(f"{a=} {b=} {c=}"))
self.contentsChange.connect(self._saveChangedContent)
@pyTTkSlot(int,int,int)
def _saveChangedContent(self,a,b,c):
if self._changedContent:
self._changedContent = TTkTextDocument._mergeChangesSlices(self._changedContent,(a,b,c))
else:
self._changedContent = (a,b,c)
if not self._refreshContent:
self._refreshContent = (self._changedContent[0], KodeTextDocument._linesRefreshed)
self._timerRefresh.start(0.1)
@pyTTkSlot()
def _refreshEvent(self):
if not self._refreshContent: return
self._kodeDocMutex.acquire()
ra,rb = self._refreshContent
if self._changedContent:
ca,cb,cc = self._changedContent
self._changedContent = None
self._blocks[ca:ca+cb] = [0]*cc
ra = min(ra,ca)
# find the beginning of the current block
# TTkLog.debug(self._blocks)
if ra and self._blocks:
blockId = self._blocks[ra]
for i,v in enumerate(reversed(self._blocks[:ra])):
# TTkLog.debug(f"{i=}:{v=} {blockId=}")
if v == blockId or not blockId:
blockId = v
ra -= 1
rb += 1
else:
break
# TTkLog.debug(f"{ra=} {rb=}")
eof = False
if (ra+rb) >= len(self._dataLines):
rb = len(self._dataLines)-ra
eof=True
tsl = self._dataLines[ra:ra+rb]
# Find the offset from the first not empty line
# because pygments autostrip the heading empty lines
offset = 0
for i,l in enumerate(tsl):
if l != '':
offset = i
break
rawl = [l._text for l in tsl[offset:]]
rawt = '\n'.join(rawl)
if not self._lexer:
try:
self._lexer = guess_lexer_for_filename(self._filePath, rawt)
except ClassNotFound:
self._lexer = special.TextLexer()
# TTkLog.debug(f"Refresh {self._lexer.name} {ra=} {rb=}")
tsl1 = [TTkString()]*(offset+1)
block = [0]*(offset+1)
kfd = KodeFormatter.Data(tsl1, block)
self._formatter.setDl(kfd)
highlight(rawt, self._lexer, self._formatter)
# for ll in tsl:
# TTkLog.debug(f"1: -{ll}-")
# for ll in tsl1:
# TTkLog.debug(f"2: -{ll}-")
tsl1 = tsl1[:rb]
block = block[:rb]
self._dataLines[ra:ra+rb] = tsl1 + tsl[len(tsl1):]
self._blocks[ra:ra+rb] = block + [-1]*(rb-len(block))
# TTkLog.debug(self._blocks)
if kfd.error is not None:
self._refreshContent = (ra+kfd.error,rb<<1)
# TTkLog.debug(f"Error: {self._refreshContent=}")
elif kfd.multiline is not None:
self._refreshContent = (ra+kfd.multiline,rb<<1)
elif (ra+rb) < len(self._dataLines):
self._refreshContent = (ra+rb,KodeTextDocument._linesRefreshed)
else:
self._refreshContent = None
# TTkLog.debug(f"{self._refreshContent=}")
if not eof:
self._timerRefresh.start(0.03)
else:
TTkLog.debug(f"Refresh {self._lexer.name} DONE!!!")
self._kodeDocMutex.release()
self.kodeHighlightUpdate.emit()
def getLock(self):
return self._kodeDocMutex
def filePath(self):
return self._filePath

31
apps/ttkode/ttkode/app/kodetextedit.py

@ -1,31 +0,0 @@
# MIT License
#
# Copyright (c) 2022 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.
from TermTk import TTkLog
from TermTk import TTkTextEditView
class KodeTextEditView(TTkTextEditView):
def keyEvent(self, evt) -> bool:
self.document().getLock().acquire()
ret = super().keyEvent(evt)
self.document().getLock().release()
return ret

103
apps/ttkode/ttkode/app/main.py

@ -22,108 +22,17 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import os
import re
import sys
__all__ = ['main']
import argparse
import appdirs
from pygments import highlight
from pygments.lexers import PythonLexer
from pygments.formatters import TerminalFormatter, Terminal256Formatter, TerminalTrueColorFormatter
from TermTk import TTk, TTkK, TTkLog, TTkCfg, TTkColor, TTkTheme, TTkTerm, TTkHelper
from TermTk import TTkString
from TermTk import TTkColorGradient
from TermTk import pyTTkSlot, pyTTkSignal
from TermTk import TTkFrame, TTkButton
from TermTk import TTkTabWidget, TTkKodeTab
from TermTk import TTkAbstractScrollArea, TTkAbstractScrollView
from TermTk import TTkFileDialogPicker
from TermTk import TTkFileTree, TTkTextEdit
from TermTk import TTkGridLayout
from TermTk import TTkSplitter
from .cfg import *
from .about import *
# from .options import optionsFormLayout, optionsLoadTheme
from .kodetextedit import KodeTextEditView
from .kodetextdocument import KodeTextDocument
class TTKode(TTkGridLayout):
__slots__ = ('_kodeTab', '_documents')
def __init__(self, *, files, **kwargs):
self._documents = {}
super().__init__(**kwargs)
self.addWidget(splitter := TTkSplitter())
layoutLeft = TTkGridLayout()
splitter.addItem(layoutLeft, 20)
hSplitter = TTkSplitter(parent=splitter, orientation=TTkK.HORIZONTAL)
menuFrame = TTkFrame(border=False, maxHeight=1)
self._kodeTab = TTkKodeTab(parent=hSplitter, border=False, closable=True)
fileMenu = menuFrame.newMenubarTop().addMenu("&File")
fileMenu.addMenu("Open").menuButtonClicked.connect(self._showFileDialog)
fileMenu.addMenu("Close") # .menuButtonClicked.connect(self._closeFile)
fileMenu.addMenu("Exit").menuButtonClicked.connect(lambda _:TTkHelper.quit())
def _showAbout(btn):
TTkHelper.overlay(None, About(), 30,10)
def _showAboutTTk(btn):
TTkHelper.overlay(None, TTkAbout(), 30,10)
helpMenu = menuFrame.newMenubarTop().addMenu("&Help", alignment=TTkK.RIGHT_ALIGN)
helpMenu.addMenu("About ...").menuButtonClicked.connect(_showAbout)
helpMenu.addMenu("About ttk").menuButtonClicked.connect(_showAboutTTk)
fileTree = TTkFileTree(path='.')
layoutLeft.addWidget(menuFrame, 0,0)
layoutLeft.addWidget(fileTree, 1,0)
layoutLeft.addWidget(quitbtn := TTkButton(border=True, text="Quit", maxHeight=3), 2,0)
quitbtn.clicked.connect(TTkHelper.quit)
for file in files:
self._openFile(file)
fileTree.fileActivated.connect(lambda x: self._openFile(x.path()))
pyTTkSlot()
def _showFileDialog(self):
filePicker = TTkFileDialogPicker(pos = (3,3), size=(75,24), caption="Pick Something", path=".", fileMode=TTkK.FileMode.AnyFile ,filter="All Files (*);;Python Files (*.py);;Bash scripts (*.sh);;Markdown Files (*.md)")
filePicker.pathPicked.connect(self._openFile)
TTkHelper.overlay(None, filePicker, 20, 5, True)
def _openFile(self, filePath):
filePath = os.path.realpath(filePath)
if filePath in self._documents:
doc = self._documents[filePath]['doc']
else:
with open(filePath, 'r') as f:
content = f.read()
doc = KodeTextDocument(text=content, filePath=filePath)
self._documents[filePath] = {'doc':doc,'tabs':[]}
tview = KodeTextEditView(document=doc, readOnly=False)
tedit = TTkTextEdit(textEditView=tview, lineNumber=True)
doc.kodeHighlightUpdate.connect(tedit.update)
label = TTkString(TTkCfg.theme.fileIcon.getIcon(filePath),TTkCfg.theme.fileIconColor) + TTkColor.RST + " " + os.path.basename(filePath)
self._kodeTab.addTab(tedit, label)
self._kodeTab.setCurrentWidget(tedit)
from TermTk import TTk, TTkTerm, TTkTheme
from TermTk import TTkLog
# def _closeFile():
# if (index := KodeTab.lastUsed.currentIndex()) >= 0:
# KodeTab.lastUsed.removeTab(index)
from .ttkode import TTKode
from .cfg import TTKodeCfg
def main():
TTKodeCfg.pathCfg = appdirs.user_config_dir("ttkode")

2
apps/ttkode/ttkode/app/options.py

@ -22,6 +22,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
__all__ = ['optionsLoadTheme', 'optionsFormLayout']
import copy
from . import TTKodeCfg, TloggGlbl

119
apps/ttkode/ttkode/app/ttkode.py

@ -0,0 +1,119 @@
#!/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.
__all__ = ['TTKode']
import os
from TermTk import TTkK, TTkLog, TTkCfg, TTkColor, TTkTheme, TTkTerm, TTkHelper
from TermTk import TTkString
from TermTk import pyTTkSlot, pyTTkSignal
from TermTk import TTkFrame, TTkButton
from TermTk import TTkKodeTab
from TermTk import TTkFileDialogPicker
from TermTk import TTkFileTree, TTkTextEdit
from TermTk import TTkGridLayout
from TermTk import TTkSplitter
from TermTk import TextDocumentHighlight
from .about import About
class _TextDocument(TextDocumentHighlight):
__slots__ = ('_filePath')
def __init__(self, filePath:str="", **kwargs):
self._filePath = filePath
super().__init__(**kwargs)
self.guessLexerFromFilename(filePath)
class TTKode(TTkGridLayout):
__slots__ = ('_kodeTab', '_documents')
def __init__(self, *, files, **kwargs):
self._documents = {}
super().__init__(**kwargs)
self.addWidget(splitter := TTkSplitter())
layoutLeft = TTkGridLayout()
splitter.addItem(layoutLeft, 20)
hSplitter = TTkSplitter(parent=splitter, orientation=TTkK.HORIZONTAL)
menuFrame = TTkFrame(border=False, maxHeight=1)
self._kodeTab = TTkKodeTab(parent=hSplitter, border=False, closable=True)
fileMenu = menuFrame.newMenubarTop().addMenu("&File")
fileMenu.addMenu("Open").menuButtonClicked.connect(self._showFileDialog)
fileMenu.addMenu("Close") # .menuButtonClicked.connect(self._closeFile)
fileMenu.addMenu("Exit").menuButtonClicked.connect(lambda _:TTkHelper.quit())
def _showAbout(btn):
TTkHelper.overlay(None, About(), 30,10)
def _showAboutTTk(btn):
TTkHelper.overlay(None, TTkAbout(), 30,10)
helpMenu = menuFrame.newMenubarTop().addMenu("&Help", alignment=TTkK.RIGHT_ALIGN)
helpMenu.addMenu("About ...").menuButtonClicked.connect(_showAbout)
helpMenu.addMenu("About ttk").menuButtonClicked.connect(_showAboutTTk)
fileTree = TTkFileTree(path='.')
layoutLeft.addWidget(menuFrame, 0,0)
layoutLeft.addWidget(fileTree, 1,0)
layoutLeft.addWidget(quitbtn := TTkButton(border=True, text="Quit", maxHeight=3), 2,0)
quitbtn.clicked.connect(TTkHelper.quit)
for file in files:
self._openFile(file)
fileTree.fileActivated.connect(lambda x: self._openFile(x.path()))
pyTTkSlot()
def _showFileDialog(self):
filePicker = TTkFileDialogPicker(pos = (3,3), size=(75,24), caption="Pick Something", path=".", fileMode=TTkK.FileMode.AnyFile ,filter="All Files (*);;Python Files (*.py);;Bash scripts (*.sh);;Markdown Files (*.md)")
filePicker.pathPicked.connect(self._openFile)
TTkHelper.overlay(None, filePicker, 20, 5, True)
def _openFile(self, filePath):
filePath = os.path.realpath(filePath)
if filePath in self._documents:
doc = self._documents[filePath]['doc']
else:
with open(filePath, 'r') as f:
content = f.read()
doc = _TextDocument(text=content, filePath=filePath)
self._documents[filePath] = {'doc':doc,'tabs':[]}
tedit = TTkTextEdit(document=doc, readOnly=False, lineNumber=True)
label = TTkString(TTkCfg.theme.fileIcon.getIcon(filePath),TTkCfg.theme.fileIconColor) + TTkColor.RST + " " + os.path.basename(filePath)
self._kodeTab.addTab(tedit, label)
self._kodeTab.setCurrentWidget(tedit)
# def _closeFile():
# if (index := KodeTab.lastUsed.currentIndex()) >= 0:
# KodeTab.lastUsed.removeTab(index)

4
libs/pyTermTk/TermTk/TTkWidgets/about.py

@ -39,7 +39,6 @@ _peppered_image = TTkUtil.base64_deflate_2_obj(
"5U2DXq3mDsvOfNqlvUa+RyTDOIh2FzT0BTmKSF6LuBkvvDOKPDpMvEXbHn1c6vRN2kpFuMgl9u2lXnzdyIBqxgR8Vh+GLZhjEoz1rDe3NTPOD+7TKdv/iBsvaPR+fnxK" +
"xQDE4uRREkUJ66XbtrnsPzh2UpZrPsLpiuSfWR4dVb7jqa6eZJnJVIxboW48rdJF2ABxDMxk73q1GcaMFpv7wcfOF+RqZ89t+64LcTjIw8OTYYtVm3J7H3cB43I6aSq0" +
"4Zf9GYaCzmMK1e6+dLH7AkxADRtZ3ojHUrmNqNtco9mqF7pzbppx0GQSQ3Op8FcJ2G5ltCNVLuI74ZeG5vr8rDHAaP/o5bQnnOawWcPyRePnp/8KRQkp")
_peppered_string = TTkString(_peppered_image)
class TTkAbout(TTkWindow):
'''
@ -94,6 +93,7 @@ class TTkAbout(TTkWindow):
[(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x21,0x00,0x00),(0x6c,0x00,0x00),(0xa2,0x00,0x00),(0x84,0x00,0x00),(0xe6,0x02,0x02),(0xff,0x3a,0x3a),(0xff,0x43,0x43),(0xec,0x05,0x04),(0x8f,0x00,0x00),(0x93,0x00,0x00),(0x65,0x00,0x00),(0x2b,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00)],
[(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x0b,0x00,0x00),(0x29,0x00,0x00),(0x30,0x00,0x00),(0x4c,0x00,0x00),(0x95,0x00,0x00),(0xa0,0x00,0x00),(0x61,0x00,0x00),(0x1a,0x00,0x00),(0x10,0x00,0x00),(0x03,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00)],
[(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00),(0x00,0x00,0x00)]]
_peppered_string = TTkString(_peppered_image)
pyTermTk = [
@ -118,7 +118,7 @@ class TTkAbout(TTkWindow):
for y, line in enumerate(TTkAbout.pyTermTk):
canvas.drawText(pos=(9,3+y),text=line, color=TTkColor.fg(f'#{c[0]:02X}{c[1]:02X}{c[2]:02X}'))
c[2]-=0x11
for i,line in enumerate(_peppered_string.split('\n')):
for i,line in enumerate(TTkAbout._peppered_string.split('\n')):
canvas.drawTTkString(pos=(1,3+i), text=line)
canvas.drawText(pos=(20, 9),text=f" Version: {TTkCfg.version}", color=TTkColor.fg('#AAAAFF'))
canvas.drawText(pos=(12,11),text=f"Powered By, Eugenio Parodi")

Loading…
Cancel
Save