12 changed files with 136 additions and 480 deletions
@ -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
|
||||
@ -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 |
||||
@ -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 |
||||
@ -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 |
||||
@ -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) |
||||
Loading…
Reference in new issue