Browse Source

Merge pull request #17 from ceccopierangiolieugenio/Table_Implementation

Moved old table/tree to 'FancyTable/Tre'
pull/18/head 0.6.0a
Ceccopierangiolieugenio 4 years ago committed by GitHub
parent
commit
c269c75ec8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      TermTk/TTkAbstract/abstractitemmodel.py
  2. 2
      TermTk/TTkCore/helper.py
  3. 9
      TermTk/TTkGui/theme.py
  4. 3
      TermTk/TTkTypes/__init__.py
  5. 6
      TermTk/TTkWidgets/Fancy/__init__.py
  6. 8
      TermTk/TTkWidgets/Fancy/table.py
  7. 16
      TermTk/TTkWidgets/Fancy/tableview.py
  8. 61
      TermTk/TTkWidgets/Fancy/tree.py
  9. 6
      TermTk/TTkWidgets/Fancy/treeview.py
  10. 157
      TermTk/TTkWidgets/Fancy/treewidget.py
  11. 14
      TermTk/TTkWidgets/Fancy/treewidgetitem.py
  12. 3
      TermTk/TTkWidgets/TTkPickers/__init__.py
  13. 43
      TermTk/TTkWidgets/TTkPickers/filepicker.py
  14. 55
      TermTk/TTkWidgets/__init__.py
  15. 6
      TermTk/TTkWidgets/splitter.py
  16. 16
      TermTk/TTkWidgets/tree.py
  17. 314
      TermTk/TTkWidgets/treewidget.py
  18. 100
      TermTk/TTkWidgets/treewidgetitem.py
  19. 2
      TermTk/TTkWidgets/widget.py
  20. 10
      demo/demo.py
  21. 2
      demo/gittk.py
  22. 6
      demo/showcase/fancytable.py
  23. 119
      demo/showcase/fancytree.py
  24. 16
      demo/showcase/tree.py
  25. 8
      docs/MDNotes/TODO.md
  26. 6
      tests/test.ui.008.fancy.table.py
  27. 88
      tests/test.ui.011.fancy.tree.py
  28. 19
      tests/test.ui.011.tree.py

8
TermTk/TTkAbstract/abstractitemmodel.py

@ -22,6 +22,12 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal
class TTkAbstractItemModel():
__slots__ = (
# Signals
'dataChanged'
)
def __init__(self, *args, **kwargs):
pass
self.dataChanged = pyTTkSignal()

2
TermTk/TTkCore/helper.py

@ -196,7 +196,7 @@ class TTkHelper:
widget.paintEvent()
# Compose all the canvas to the parents
# From the deepest childs to the bottom
# From the deepest children to the bottom
pushToTerminal = False
sortedUpdateWidget = [ (w, TTkHelper.widgetDepth(w)) for w in updateWidgets]
sortedUpdateWidget = sorted(sortedUpdateWidget, key=lambda w: -w[1])

9
TermTk/TTkGui/theme.py

@ -115,8 +115,6 @@ class TTkTheme():
'''
buttonBox = (
('','','',
'',' ','',
@ -136,6 +134,10 @@ class TTkTheme():
hscroll = ('','','','')
vscroll = ('','','','')
tree = ('','','',' ',
'','')
# 0 1 2 3 4 5
menuBar = ('','','','','','')
@ -268,3 +270,6 @@ class TTkTheme():
tabOffsetColorFocus = tabOffsetColor
tabBorderColorFocus = TTkColor.fg("#ffff88")
tabSelectColorFocus = TTkColor.fg("#ffff88")+TTkColor.bg("#000066")+TTkColor.BOLD
treeHeaderColor = TTkColor.fg("#ffffff")+TTkColor.bg("#444444")+TTkColor.BOLD
treeSelectedColor = TTkColor.fg("#ffff88")+TTkColor.bg("#000066")+TTkColor.BOLD

3
TermTk/TTkTypes/__init__.py

@ -1,2 +1 @@
from .viewitem import *
from .treewidgetitem import *
from .viewitem import *

6
TermTk/TTkWidgets/Fancy/__init__.py

@ -0,0 +1,6 @@
from .table import *
from .tableview import *
from .tree import *
from .treeview import *
from .treewidget import *
from .treewidgetitem import *

8
TermTk/TTkWidgets/table.py → TermTk/TTkWidgets/Fancy/table.py

@ -27,11 +27,11 @@ from TermTk.TTkCore.constant import TTkK
from TermTk.TTkCore.log import TTkLog
from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal
from TermTk.TTkCore.color import TTkColor
from TermTk.TTkWidgets.tableview import TTkTableView
from TermTk.TTkWidgets.Fancy.tableview import TTkFancyTableView
from TermTk.TTkLayouts.gridlayout import TTkGridLayout
from TermTk.TTkAbstract.abstractscrollarea import TTkAbstractScrollArea
class TTkTable(TTkAbstractScrollArea):
class TTkFancyTable(TTkAbstractScrollArea):
__slots__ = (
'_tableView', 'activated',
# Forwarded Methods
@ -42,9 +42,9 @@ class TTkTable(TTkAbstractScrollArea):
def __init__(self, *args, **kwargs):
TTkAbstractScrollArea.__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , 'TTkTable' )
self._name = kwargs.get('name' , 'TTkFancyTable' )
if 'parent' in kwargs: kwargs.pop('parent')
self._tableView = TTkTableView(*args, **kwargs)
self._tableView = TTkFancyTableView(*args, **kwargs)
# Forward the signal
self.activated = self._tableView.activated

16
TermTk/TTkWidgets/tableview.py → TermTk/TTkWidgets/Fancy/tableview.py

@ -31,11 +31,11 @@ from TermTk.TTkWidgets.widget import TTkWidget
from TermTk.TTkLayouts.gridlayout import TTkGridLayout
from TermTk.TTkAbstract.abstractscrollview import TTkAbstractScrollView
class _TTkTableViewHeader(TTkWidget):
class _TTkFancyTableViewHeader(TTkWidget):
__slots__ = ('_header', '_alignments', '_headerColor', '_columns')
def __init__(self, *args, **kwargs):
TTkWidget.__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , '_TTkTableViewHeader' )
self._name = kwargs.get('name' , '_TTkFancyTableViewHeader' )
self._columns = kwargs.get('columns' , [-1] )
self._header = [""]*len(self._columns)
self._alignments = [TTkK.NONE]*len(self._columns)
@ -80,7 +80,7 @@ class _TTkTableViewHeader(TTkWidget):
self._canvas.drawTableLine(pos=(0,0), items=self._header, sizes=sizes, colors=colors, alignments=self._alignments)
class _TTkTableView(TTkAbstractScrollView):
class _TTkFancyTableView(TTkAbstractScrollView):
__slots__ = (
'_alignments', '_headerColor',
'_columns', '_columnColors',
@ -94,7 +94,7 @@ class _TTkTableView(TTkAbstractScrollView):
self._tableDataWidget = []
self._shownWidgets = []
TTkAbstractScrollView.__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , '_TTkTableView' )
self._name = kwargs.get('name' , '_TTkFancyTableView' )
# define signals
self.activated = pyTTkSignal(int) # Value
self.doubleClicked = pyTTkSignal(int) # Value
@ -335,7 +335,7 @@ class _TTkTableView(TTkAbstractScrollView):
colors = [c.modParam(val=-val) for c in self._columnColors]
self._canvas.drawTableLine(pos=(0,y), items=item, sizes=sizes, colors=colors, alignments=self._alignments)
class TTkTableView(TTkAbstractScrollView):
class TTkFancyTableView(TTkAbstractScrollView):
__slots__ = (
'_header', '_tableView', '_showHeader', 'activated',
# Forwarded Methods
@ -344,12 +344,12 @@ class TTkTableView(TTkAbstractScrollView):
def __init__(self, *args, **kwargs):
super().__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , 'TTkTableView' )
self._name = kwargs.get('name' , 'TTkFancyTableView' )
if 'parent' in kwargs: kwargs.pop('parent')
self._showHeader = kwargs.get('showHeader', True)
self.setLayout(TTkGridLayout())
self._tableView = _TTkTableView(*args, **kwargs)
self._header = _TTkTableViewHeader(*args, **kwargs)
self._tableView = _TTkFancyTableView(*args, **kwargs)
self._header = _TTkFancyTableViewHeader(*args, **kwargs)
self.layout().addWidget(self._header,0,0)
self.layout().addWidget(self._tableView,1,0)
# Forward the tableSignals

61
TermTk/TTkWidgets/Fancy/tree.py

@ -0,0 +1,61 @@
#!/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.
from TermTk.TTkCore.cfg import TTkCfg
from TermTk.TTkCore.constant import TTkK
from TermTk.TTkCore.log import TTkLog
from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal
from TermTk.TTkCore.color import TTkColor
from TermTk.TTkWidgets.Fancy.treewidget import TTkFancyTreeWidget
from TermTk.TTkLayouts.gridlayout import TTkGridLayout
from TermTk.TTkAbstract.abstractscrollarea import TTkAbstractScrollArea
class TTkFancyTree(TTkAbstractScrollArea):
__slots__ = (
'_treeView', 'activated',
# Forwarded Methods
'setAlignment', 'setHeader', 'setHeaderLabels', 'setColumnSize', 'setColumnColors', 'appendItem', 'addTopLevelItem' )
def __init__(self, *args, **kwargs):
TTkAbstractScrollArea.__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , 'TTkFancyTree' )
if 'parent' in kwargs: kwargs.pop('parent')
self._treeView = TTkFancyTreeWidget(*args, **kwargs)
# Forward the signal
self.activated = self._treeView.activated
self.setFocusPolicy(TTkK.ClickFocus)
self.setViewport(self._treeView)
# Forwarded Methods
self.setAlignment = self._treeView.setAlignment
self.setHeader = self._treeView.setHeader
self.setHeaderLabels = self._treeView.setHeaderLabels
self.setColumnSize = self._treeView.setColumnSize
self.setColumnColors = self._treeView.setColumnColors
self.appendItem = self._treeView.appendItem
self.addTopLevelItem = self._treeView.addTopLevelItem

6
TermTk/TTkWidgets/treeview.py → TermTk/TTkWidgets/Fancy/treeview.py

@ -27,13 +27,13 @@ from TermTk.TTkCore.constant import TTkK
from TermTk.TTkCore.log import TTkLog
from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal
from TermTk.TTkCore.color import TTkColor
from TermTk.TTkWidgets.tableview import TTkTableView
from TermTk.TTkWidgets.Fancy.tableview import TTkFancyTableView
class TTkTreeView(TTkTableView):
class TTkFancyTreeView(TTkFancyTableView):
__slots__ = ( '_header', '_treeView', '_showHeader', 'activated')
def __init__(self, *args, **kwargs):
super().__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , 'TTkTreeView' )
self._name = kwargs.get('name' , 'TTkFancyTreeView' )
# if 'parent' in kwargs: kwargs.pop('parent')

157
TermTk/TTkWidgets/Fancy/treewidget.py

@ -0,0 +1,157 @@
#!/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.
from TermTk.TTkCore.cfg import TTkCfg
from TermTk.TTkCore.constant import TTkK
from TermTk.TTkCore.log import TTkLog
from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal
from TermTk.TTkCore.color import TTkColor
from TermTk.TTkWidgets.widget import TTkWidget
from TermTk.TTkWidgets.checkbox import TTkCheckbox
from TermTk.TTkLayouts.gridlayout import TTkGridLayout
from TermTk.TTkWidgets.Fancy.tableview import TTkFancyTableView
from TermTk.TTkWidgets.Fancy.treewidgetitem import TTkFancyTreeWidgetItem
class _TTkDisplayedTreeItemControl(TTkCheckbox):
def __init__(self, *args, **kwargs):
super().__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , '_TTkDisplayedTreeItemControl' )
self.setMinimumSize(1, 1)
def paintEvent(self):
if self._checked:
self._canvas.drawText(pos=(0,0), text="")
else:
self._canvas.drawText(pos=(0,0), text="")
class _TTkDisplayedTreeItem(TTkWidget):
__slots__ = ('_depth', '_control', '_text', '_id', '_clicked', '_treeWidgetItem', '_isLeaf' )
def __init__(self, *args, **kwargs):
super().__init__(self, *args, **kwargs)
#Signals
self._clicked = pyTTkSignal(bool, _TTkDisplayedTreeItem, TTkFancyTreeWidgetItem)
self._name = kwargs.get('name' , '_TTkDisplayedTreeItem' )
self._depth = kwargs.get('depth' , 0 )
self._text = kwargs.get('text' , "" )
self._id = kwargs.get('id' , 0 )
self._treeWidgetItem = kwargs.get('treeWidgetItem', None)
self._isLeaf = self._treeWidgetItem.childIndicatorPolicy() == TTkK.DontShowIndicator
self._isLeaf |= self._treeWidgetItem.childIndicatorPolicy() == TTkK.DontShowIndicatorWhenChildless and not self._treeWidgetItem.children()
if self._isLeaf:
self._control = None
else:
self._control = _TTkDisplayedTreeItemControl(parent=self, checked=self._treeWidgetItem.expand())
self._control.setGeometry(self._depth, 0, 1, 1)
self._control.clicked.connect(self._controlClicked)
@pyTTkSlot(bool)
def _controlClicked(self, status):
self._clicked.emit(status, self, self._treeWidgetItem)
def paintEvent(self):
if self._isLeaf:
self._canvas.drawText(pos=(self._depth, 0), text="")
self._canvas.drawText(pos=(self._depth+2, 0), text=self._text)
class TTkFancyTreeWidget(TTkFancyTableView):
__slots__ = ( '_topLevelItems')
def __init__(self, *args, **kwargs):
super().__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , 'TTkFancyTreeView' )
self._topLevelItems = TTkFancyTreeWidgetItem(None)
self.doubleClicked.connect(self._doubleClickItem)
# if 'parent' in kwargs: kwargs.pop('parent')
def _expand(self, item, depth):
item.setExpand(True)
item.refresh()
toExpand = []
index = self.indexOf(item.data())+1
if index != 0:
for child in item.children():
self._addTreeWidgetItem(item=child, depth=depth, index=index)
index+=1
if child.expand():
toExpand.append(child)
for child in toExpand:
self._expand(item=child, depth=(depth+1))
def _shrink(self, item):
item.setExpand(False)
item.refresh()
index = self.indexOf(item.data())
parent = item.parent()
if item == parent.children()[-1]:
self.removeItemsFrom(index+1)
else:
nextItemIndex = parent.children().index(item)
nextItem = parent.children()[nextItemIndex+1]
indexTo = self.indexOf(nextItem.data())
for id in reversed(range(index+1,indexTo)):
self.removeItemAt(id)
@pyTTkSlot(int)
def _doubleClickItem(self, index):
if not (item := self.itemAt(index)): return
if item[0]._isLeaf: return
if not item[0]._treeWidgetItem.expand(): # we need to expand the TTkFancyTreeWidgetItem
self._expand(item=item[0]._treeWidgetItem, depth=item[0]._depth+1)
else: # we need to shrink the TTkFancyTreeWidgetItem
self._shrink(item=item[0]._treeWidgetItem)
@pyTTkSlot(bool, _TTkDisplayedTreeItem, TTkFancyTreeWidgetItem)
def _controlClicked(self, status, widget, item):
TTkLog.debug(f"{status} {widget._name}")
if status: # we need to expand the TTkFancyTreeWidgetItem
self._expand(item=item, depth=(widget._depth+1))
else: # we need to shrink the TTkFancyTreeWidgetItem
self._shrink(item=item)
def _addTreeWidgetItem(self, item, depth=0, index=-1):
if not isinstance(item, TTkFancyTreeWidgetItem):
raise TypeError("TTkFancyTreeWidgetItem is required in TTkFancyTreeWidget.addTopLevelItem(item)")
if item.parent() is None:
self._topLevelItems.addChild(item)
displayedItems = item.data().copy()
displayTreeItem = _TTkDisplayedTreeItem(text=displayedItems[0], id=0, depth=depth, treeWidgetItem=item)
displayTreeItem._clicked.connect(self._controlClicked)
displayedItems[0] = displayTreeItem
if index == -1:
self.appendItem(item=displayedItems, id=item.data())
else:
self.insertItem(item=displayedItems, id=item.data(), index=index, )
def addTopLevelItem(self, item):
self._addTreeWidgetItem(item)
def setHeaderLabels(self, labels):
columns = [-1]*len(labels)
self.setColumnSize(columns)
self.setHeader(labels)

14
TermTk/TTkTypes/treewidgetitem.py → TermTk/TTkWidgets/Fancy/treewidgetitem.py

@ -27,15 +27,15 @@ from TermTk.TTkCore.constant import TTkK
from TermTk.TTkCore.log import TTkLog
from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal
class TTkTreeWidgetItem():
__slots__ = ('_parent', '_data', '_childs', '_expand', '_childIndicatorPolicy',
class TTkFancyTreeWidgetItem():
__slots__ = ('_parent', '_data', '_children', '_expand', '_childIndicatorPolicy',
# Signals
'refreshData')
def __init__(self, *args, **kwargs):
# Signals
self.refreshData = pyTTkSignal(TTkTreeWidgetItem)
self.refreshData = pyTTkSignal(TTkFancyTreeWidgetItem)
self._data = args[0]
self._childs = []
self._children = []
self._childIndicatorPolicy = kwargs.get('childIndicatorPolicy', TTkK.DontShowIndicatorWhenChildless)
self._expand = False
self._parent = kwargs.get("parent", None)
@ -56,7 +56,7 @@ class TTkTreeWidgetItem():
return self._expand
def addChild(self, item):
self._childs.append(item)
self._children.append(item)
item._parent = self
def data(self):
@ -65,5 +65,5 @@ class TTkTreeWidgetItem():
def parent(self):
return self._parent
def childs(self):
return self._childs
def children(self):
return self._children

3
TermTk/TTkWidgets/TTkPickers/__init__.py

@ -1 +1,2 @@
from .colorpicker import *
from .colorpicker import *
from .filepicker import *

43
TermTk/TTkWidgets/TTkPickers/filepicker.py

@ -0,0 +1,43 @@
#!/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.
from os import walk
from TermTk.TTkWidgets.window import TTkWindow
from TermTk.TTkWidgets.Fancy.treewidgetitem import TTkFancyTreeWidgetItem
class _FileWidgetItem(TTkFancyTreeWidgetItem):
def __init__(self, *args, **kwargs):
TTkFancyTreeWidgetItem.__init__(self, *args, **kwargs)
class TTkFileDialogPicker(TTkWindow):
def __init__(self, *args, **kwargs):
TTkWindow.__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , 'TTkFileDialogPicker' )
'''
for (dirpath, dirnames, filenames) in walk('/tmp'):
print(f"{dirpath} {dirnames} {filenames}")
break
'''

55
TermTk/TTkWidgets/__init__.py

@ -1,29 +1,28 @@
from .widget import *
from .spacer import *
from .frame import *
from .widget import *
from .spacer import *
from .frame import *
from .resizableframe import *
from .splitter import *
from .label import *
from .button import *
from .checkbox import *
from .radiobutton import *
from .combobox import *
from .lineedit import *
from .texedit import *
from .scrollbar import *
from .scrollarea import *
from .window import *
from .tabwidget import *
from .list_ import *
from .listwidget import *
from .table import *
from .tableview import *
from .tree import *
from .treeview import *
from .treewidget import *
from .graph import *
from .menubar import *
from .TTkPickers import *
from .spinbox import *
from .image import TTkImage
from .about import TTkAbout
from .splitter import *
from .label import *
from .button import *
from .checkbox import *
from .radiobutton import *
from .combobox import *
from .lineedit import *
from .texedit import *
from .scrollbar import *
from .scrollarea import *
from .window import *
from .tabwidget import *
from .list_ import *
from .listwidget import *
from .graph import *
from .menubar import *
from .TTkPickers import *
from .spinbox import *
from .image import TTkImage
from .about import TTkAbout
from .tree import TTkTree
from .treewidget import TTkTreeWidget
from .treewidgetitem import TTkTreeWidgetItem
from .Fancy import *

6
TermTk/TTkWidgets/splitter.py

@ -32,7 +32,7 @@ class TTkSplitter(TTkFrame):
__slots__ = (
'_splitterInitialized', '_orientation',
'_separators', '_separatorsRef', '_sizeRef', '_initSizes',
'_separatorSelected', '_mouseDelta')
'_separatorSelected')
def __init__(self, *args, **kwargs):
self._splitterInitialized = False
# self._splitterInitialized = True
@ -194,11 +194,9 @@ class TTkSplitter(TTkFrame):
def mousePressEvent(self, evt):
self._separatorSelected = None
self._mouseDelta = (evt.x, evt.y)
x,y = evt.x, evt.y
# TTkLog.debug(f"{self._separators} {evt}")
for i in range(len(self._separators)):
val = self._separators[i]
for i, val in enumerate(self._separators):
if self._orientation == TTkK.HORIZONTAL:
if x == val:
self._separatorSelected = i

16
TermTk/TTkWidgets/tree.py

@ -22,13 +22,9 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from TermTk.TTkCore.cfg import TTkCfg
from TermTk.TTkCore.constant import TTkK
from TermTk.TTkCore.log import TTkLog
from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal
from TermTk.TTkCore.color import TTkColor
from TermTk.TTkWidgets.treewidget import TTkTreeWidget
from TermTk.TTkLayouts.gridlayout import TTkGridLayout
from TermTk.TTkAbstract.abstractscrollarea import TTkAbstractScrollArea
class TTkTree(TTkAbstractScrollArea):
@ -43,18 +39,18 @@ class TTkTree(TTkAbstractScrollArea):
if 'parent' in kwargs: kwargs.pop('parent')
self._treeView = TTkTreeWidget(*args, **kwargs)
# Forward the signal
self.activated = self._treeView.activated
# self.activated = self._treeView.activated
self.setFocusPolicy(TTkK.ClickFocus)
self.setViewport(self._treeView)
# Forwarded Methods
self.setAlignment = self._treeView.setAlignment
self.setHeader = self._treeView.setHeader
#self.setAlignment = self._treeView.setAlignment
#self.setHeader = self._treeView.setHeader
self.setHeaderLabels = self._treeView.setHeaderLabels
self.setColumnSize = self._treeView.setColumnSize
self.setColumnColors = self._treeView.setColumnColors
self.appendItem = self._treeView.appendItem
#self.setColumnSize = self._treeView.setColumnSize
#self.setColumnColors = self._treeView.setColumnColors
#self.appendItem = self._treeView.appendItem
self.addTopLevelItem = self._treeView.addTopLevelItem

314
TermTk/TTkWidgets/treewidget.py

@ -23,135 +23,205 @@
# SOFTWARE.
from TermTk.TTkCore.cfg import TTkCfg
from TermTk.TTkCore.color import TTkColor
from TermTk.TTkCore.constant import TTkK
from TermTk.TTkCore.log import TTkLog
from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal
from TermTk.TTkCore.color import TTkColor
from TermTk.TTkWidgets.widget import TTkWidget
from TermTk.TTkWidgets.checkbox import TTkCheckbox
from TermTk.TTkWidgets.tableview import TTkTableView
from TermTk.TTkLayouts.gridlayout import TTkGridLayout
from TermTk.TTkTypes.treewidgetitem import TTkTreeWidgetItem
class _TTkDisplayedTreeItemControl(TTkCheckbox):
def __init__(self, *args, **kwargs):
super().__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , '_TTkDisplayedTreeItemControl' )
self.setMinimumSize(1, 1)
def paintEvent(self):
if self._checked:
self._canvas.drawText(pos=(0,0), text="")
else:
self._canvas.drawText(pos=(0,0), text="")
class _TTkDisplayedTreeItem(TTkWidget):
__slots__ = ('_depth', '_control', '_text', '_id', '_clicked', '_treeWidgetItem', '_isLeaf' )
def __init__(self, *args, **kwargs):
super().__init__(self, *args, **kwargs)
#Signals
self._clicked = pyTTkSignal(bool, _TTkDisplayedTreeItem, TTkTreeWidgetItem)
self._name = kwargs.get('name' , '_TTkDisplayedTreeItem' )
self._depth = kwargs.get('depth' , 0 )
self._text = kwargs.get('text' , "" )
self._id = kwargs.get('id' , 0 )
self._treeWidgetItem = kwargs.get('treeWidgetItem', None)
self._isLeaf = self._treeWidgetItem.childIndicatorPolicy() == TTkK.DontShowIndicator
self._isLeaf |= self._treeWidgetItem.childIndicatorPolicy() == TTkK.DontShowIndicatorWhenChildless and not self._treeWidgetItem.childs()
if self._isLeaf:
self._control = None
else:
self._control = _TTkDisplayedTreeItemControl(parent=self, checked=self._treeWidgetItem.expand())
self._control.setGeometry(self._depth, 0, 1, 1)
self._control.clicked.connect(self._controlClicked)
@pyTTkSlot(bool)
def _controlClicked(self, status):
self._clicked.emit(status, self, self._treeWidgetItem)
def paintEvent(self):
if self._isLeaf:
self._canvas.drawText(pos=(self._depth, 0), text="")
self._canvas.drawText(pos=(self._depth+2, 0), text=self._text)
class TTkTreeWidget(TTkTableView):
__slots__ = ( '_topLevelItems')
from TermTk.TTkWidgets.treewidgetitem import TTkTreeWidgetItem
from TermTk.TTkAbstract.abstractscrollarea import TTkAbstractScrollView
from TermTk.TTkCore.signal import pyTTkSlot
from dataclasses import dataclass
class TTkTreeWidget(TTkAbstractScrollView):
__slots__ = ( '_items', '_header', '_columnsPos', '_cache',
'_selectedId', '_selected', '_separatorSelected', '_mouseDelta',
'_headerColor', '_selectedColor')
@dataclass(frozen=True)
class _Cache:
item: TTkTreeWidgetItem
level: int
data: list
def __init__(self, *args, **kwargs):
super().__init__(self, *args, **kwargs)
self._name = kwargs.get('name' , 'TTkTreeView' )
self._topLevelItems = TTkTreeWidgetItem(None)
self.doubleClicked.connect(self._doubleClickItem)
# if 'parent' in kwargs: kwargs.pop('parent')
def _expand(self, item, depth):
item.setExpand(True)
item.refresh()
toExpand = []
index = self.indexOf(item.data())+1
if index != 0:
for child in item.childs():
self._addTreeWidgetItem(item=child, depth=depth, index=index)
index+=1
if child.expand():
toExpand.append(child)
for child in toExpand:
self._expand(item=child, depth=(depth+1))
def _shrink(self, item):
item.setExpand(False)
item.refresh()
index = self.indexOf(item.data())
parent = item.parent()
if item == parent.childs()[-1]:
self.removeItemsFrom(index+1)
else:
nextItemIndex = parent.childs().index(item)
nextItem = parent.childs()[nextItemIndex+1]
indexTo = self.indexOf(nextItem.data())
for id in reversed(range(index+1,indexTo)):
self.removeItemAt(id)
@pyTTkSlot(int)
def _doubleClickItem(self, index):
if not (item := self.itemAt(index)): return
if item[0]._isLeaf: return
if not item[0]._treeWidgetItem.expand(): # we need to expand the TtkTreeWidgetItem
self._expand(item=item[0]._treeWidgetItem, depth=item[0]._depth+1)
else: # we need to shrink the TtkTreeWidgetItem
self._shrink(item=item[0]._treeWidgetItem)
@pyTTkSlot(bool, _TTkDisplayedTreeItem, TTkTreeWidgetItem)
def _controlClicked(self, status, widget, item):
TTkLog.debug(f"{status} {widget._name}")
if status: # we need to expand the TtkTreeWidgetItem
self._expand(item=item, depth=(widget._depth+1))
else: # we need to shrink the TtkTreeWidgetItem
self._shrink(item=item)
def _addTreeWidgetItem(self, item, depth=0, index=-1):
if not isinstance(item, TTkTreeWidgetItem):
raise TypeError("TTkTreeWidgetItem is required in TTkTreeWidget.addTopLevelItem(item)")
if item.parent() is None:
self._topLevelItems.addChild(item)
displayedItems = item.data().copy()
displayTreeItem = _TTkDisplayedTreeItem(text=displayedItems[0], id=0, depth=depth, treeWidgetItem=item)
displayTreeItem._clicked.connect(self._controlClicked)
displayedItems[0] = displayTreeItem
if index == -1:
self.appendItem(item=displayedItems, id=item.data())
else:
self.insertItem(item=displayedItems, id=item.data(), index=index, )
self._selected = None
self._selectedId = None
self._separatorSelected = None
self._items = []
self._header = kwargs.get('header',[])
self._columnsPos = []
self._cache = []
self._headerColor = kwargs.get('headerColor',TTkCfg.theme.treeHeaderColor)
self._selectedColor = kwargs.get('selectedColor',TTkCfg.theme.treeSelectedColor)
self.setMinimumHeight(1)
self.setFocusPolicy(TTkK.ClickFocus)
# Overridden function
def viewFullAreaSize(self) -> (int, int):
w = self._columnsPos[-1] if self._columnsPos else 0
h = 1+sum([c.size() for c in self._items])
# TTkLog.debug(f"{w=} {h=}")
return w,h
# Overridden function
def viewDisplayedSize(self) -> (int, int):
# TTkLog.debug(f"{self.size()=}")
return self.size()
def addTopLevelItem(self, item):
self._addTreeWidgetItem(item)
item.dataChanged.connect(self._refreshCache)
self._items.append(item)
self._refreshCache()
self.viewChanged.emit()
self.update()
def setHeaderLabels(self, labels):
columns = [-1]*len(labels)
self.setColumnSize(columns)
self.setHeader(labels)
self._header = labels
# Set 20 as default column size
self._columnsPos = [20+x*20 for x in range(len(labels))]
self.viewChanged.emit()
self.update()
def mouseDoubleClickEvent(self, evt):
_,y = evt.x, evt.y
_, oy = self.getViewOffsets()
y -= 1-oy
if 0 <= y < len(self._cache):
item = self._cache[y].item
item.setExpanded(not item.isExpanded())
if self._selected:
self._selected.setSelected(False)
self._selectedId = y
self._selected = item
self._selected.setSelected(True)
self.update()
return True
def focusOutEvent(self):
self._separatorSelected = None
def mousePressEvent(self, evt):
x,y = evt.x, evt.y
ox, oy = self.getViewOffsets()
x += ox
self._separatorSelected = None
self._mouseDelta = (evt.x, evt.y)
# Handle Header Events
if y == 0:
for i, c in enumerate(self._columnsPos):
if x == c:
self._separatorSelected = i
self.update()
return True
# Handle Tree/Table Events
y += oy-1
if 0 <= y < len(self._cache):
item = self._cache[y].item
level = self._cache[y].level
if level*2 <= x < level*2+3:
item.setExpanded(not item.isExpanded())
else:
if self._selected:
self._selected.setSelected(False)
self._selectedId = y
self._selected = item
self._selected.setSelected(True)
self.update()
return True
def mouseDragEvent(self, evt):
'''
::
columnPos (Selected = 2)
0 1 2 3 4
----|-------|--------|----------|---|
Mouse (Drag) Pos
^
I consider at least 4 char (3+1) as spacing
Min Selected Pos = (Selected+1) * 4
'''
if self._separatorSelected is not None:
x,y = evt.x, evt.y
ox, oy = self.getViewOffsets()
y += oy
x += ox
ss = self._separatorSelected
pos = max((ss+1)*4, x)
self._columnsPos[ss] = pos
# Align the previous Separators if pushed
for i in range(ss):
self._columnsPos[i] = min(self._columnsPos[i], pos-(ss-i)*4)
# Align the next Separators if pushed
for i in range(ss, len(self._columnsPos)):
self._columnsPos[i] = max(self._columnsPos[i], pos+(i-ss)*4)
self.update()
self.viewChanged.emit()
return True
return False
@pyTTkSlot()
def _refreshCache(self):
''' I save a representation fo the displayed tree in a cache array
to avoid eccessve recursion over the items and
identify quickly the nth displayed line to improve the interaction
_cache is an array of TTkTreeWidget._Cache:
[ item, level, data=[txtCol1, txtCol2, txtCol3, ... ]]
'''
self._cache = []
def _addToCache(_child, _level):
tt = TTkCfg.theme.tree
_data = []
for _il in range(len(self._header)):
_data.append(_child.data(_il))
if not _child.children():
_data[0] = f"{' '*_level} {tt[0]} {_data[0]}"
elif _child.isExpanded():
_data[0] = f"{' '*_level} {tt[2]} {_data[0]}"
else:
_data[0] = f"{' '*_level} {tt[1]} {_data[0]}"
self._cache.append(TTkTreeWidget._Cache(
item = _child,
level = _level,
data = _data))
if _child.isExpanded():
for _c in _child.children():
_addToCache(_c, _level+1)
for c in self._items:
_addToCache(c,0)
self.update()
self.viewChanged.emit()
def paintEvent(self):
x,y = self.getViewOffsets()
w,h = self.size()
tt = TTkCfg.theme.tree
# Draw header first:
for i,l in enumerate(self._header):
hx = 0 if i==0 else self._columnsPos[i-1]+1
hx1 = self._columnsPos[i]
self._canvas.drawText(pos=(hx-x,0), text=l, width=hx1-hx, color=self._headerColor)
# Draw header separators
for sx in self._columnsPos:
self._canvas.drawChar(pos=(sx-x,0), char=tt[5], color=self._headerColor)
for sy in range(1,h):
self._canvas.drawChar(pos=(sx-x,sy), char=tt[4])
# Draw cache
for i, c in enumerate(self._cache):
if i-y<0 : continue
item = c.item
level = c.level
color = self._selectedColor if item.isSelected() else TTkColor.RST
for il in range(len(self._header)):
lx = 0 if il==0 else self._columnsPos[il-1]+1
lx1 = self._columnsPos[il]
self._canvas.drawText(pos=(lx-x,i-y+1), text=c.data[il], width=lx1-lx, color=color)

100
TermTk/TTkWidgets/treewidgetitem.py

@ -0,0 +1,100 @@
#!/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.
from TermTk.TTkCore.cfg import TTkCfg
from TermTk.TTkCore.constant import TTkK
from TermTk.TTkCore.log import TTkLog
from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal
from TermTk.TTkAbstract.abstractitemmodel import TTkAbstractItemModel
class TTkTreeWidgetItem(TTkAbstractItemModel):
__slots__ = ('_parent', '_data', '_children', '_expanded', '_selected',
'_childIndicatorPolicy',
# Signals
'refreshData')
def __init__(self, *args, **kwargs):
# Signals
self.refreshData = pyTTkSignal(TTkTreeWidgetItem)
super().__init__(self, *args, **kwargs)
self._children = []
self._data = args[0] if len(args)>0 and type(args[0])==list else None
self._parent = kwargs.get('parent', None)
self._childIndicatorPolicy = kwargs.get('childIndicatorPolicy', TTkK.DontShowIndicatorWhenChildless)
self._expanded = False
self._selected = False
self._parent = kwargs.get("parent", None)
def addChild(self, child):
self._children.append(child)
child._parent = self
child.dataChanged.connect(self.emitDataChanged)
self.dataChanged.emit()
def addChildren(self, children):
for child in children:
self.addChild(child)
def child(self, index):
if 0 <= index < len(self._children):
return self._children[index]
return None
def children(self):
return self._children
def data(self, column, role=None):
if column >= len(self._data):
return None
return self._data[column]
@pyTTkSlot()
def emitDataChanged(self):
self.dataChanged.emit()
# def setDisabled(disabled):
# pass
def setExpanded(self, expand):
self._expanded = expand
self.emitDataChanged()
def setSelected(self, select):
self._selected = select
# def isDisabled():
# pass
def isExpanded(self):
return self._expanded
def isSelected(self):
return self._selected
def size(self):
if self._expanded:
return 1 + sum([c.size() for c in self._children])
else:
return 1

2
TermTk/TTkWidgets/widget.py

@ -48,7 +48,7 @@ class TTkWidget(TMouseEvents,TKeyEvents):
(x,y)
padt (Top Padding)
height
padl Layout/childs padr
padl Layout/child padr
padb (Bottom Pad.)

10
demo/demo.py

@ -32,9 +32,7 @@ import TermTk as ttk
from showcase.layout_basic import demoLayout
from showcase.layout_nested import demoLayoutNested
from showcase.layout_span import demoLayoutSpan
from showcase.table import demoTable
from showcase.tab import demoTab
from showcase.tree import demoTree
from showcase.graph import demoGraph
from showcase.splitter import demoSplitter
from showcase.windows import demoWindows
@ -43,6 +41,9 @@ from showcase.scrollarea import demoScrollArea
from showcase.list import demoList
from showcase.menubar import demoMenuBar
from showcase.colorpicker import demoColorPicker
from showcase.tree import demoTree
from showcase.fancytable import demoFancyTable
from showcase.fancytree import demoFancyTree
words = ["Lorem", "ipsum", "dolor", "sit", "amet,", "consectetur", "adipiscing", "elit,", "sed", "do", "eiusmod", "tempor", "incididunt", "ut", "labore", "et", "dolore", "magna", "aliqua.", "Ut", "enim", "ad", "minim", "veniam,", "quis", "nostrud", "exercitation", "ullamco", "laboris", "nisi", "ut", "aliquip", "ex", "ea", "commodo", "consequat.", "Duis", "aute", "irure", "dolor", "in", "reprehenderit", "in", "voluptate", "velit", "esse", "cillum", "dolore", "eu", "fugiat", "nulla", "pariatur.", "Excepteur", "sint", "occaecat", "cupidatat", "non", "proident,", "sunt", "in", "culpa", "qui", "officia", "deserunt", "mollit", "anim", "id", "est", "laborum."]
def getWord():
@ -78,9 +79,10 @@ def demoShowcase(root=None, border=True):
tabWidgets = ttk.TTkTabWidget(parent=mainFrame, border=False, visible=False)
tabWidgets.addTab(demoFormWidgets(), " Form Test ")
tabWidgets.addTab(demoList(), " List Test ")
tabWidgets.addTab(demoTable(), " Table Test ")
tabWidgets.addTab(demoTree(), " Tree Test ")
tabWidgets.addTab(demoTree(), " Tree Test")
tabWidgets.addTab(demoTab(), " Tab Test ")
tabWidgets.addTab(demoFancyTable(), " Old Table ")
tabWidgets.addTab(demoFancyTree(), " Old Tree ")
listMenu.addItem(f"Pickers")
tabPickers = ttk.TTkTabWidget(parent=mainFrame, border=False, visible=False)

2
demo/gittk.py

@ -59,7 +59,7 @@ else:
gittk = ttk.TTkWindow(parent=root,pos = (1,1), size=(100,40), title="gittk", border=True, layout=ttk.TTkGridLayout())
gittkVsplitter = ttk.TTkSplitter(parent=gittk, orientation=ttk.TTkK.VERTICAL)
tableCommit = ttk.TTkTable(parent=gittkVsplitter, selectColor=ttk.TTkColor.bg('#882200'))
tableCommit = ttk.TTkFancyTable(parent=gittkVsplitter, selectColor=ttk.TTkColor.bg('#882200'))
gittkHsplitter = ttk.TTkSplitter(parent=gittkVsplitter, orientation=ttk.TTkK.HORIZONTAL)
diffText = ttk.TTkTextEdit(parent=gittkHsplitter)
gittkHsplitter.addWidget(ttk.TTkTestWidgetSizes(border=True, title="Details"),20)

6
demo/showcase/table.py → demo/showcase/fancytable.py

@ -36,13 +36,13 @@ def getSentence(a,b):
table_ii = 1000
def demoTable(root=None):
def demoFancyTable(root=None):
frame = ttk.TTkFrame(parent=root, border=False, layout=ttk.TTkVBoxLayout())
top = ttk.TTkFrame(parent=frame, border=False, layout=ttk.TTkHBoxLayout())
btn1 = ttk.TTkButton(parent=top, maxHeight=3, border=True, text='Add')
btn2 = ttk.TTkButton(parent=top, maxHeight=3, border=True, text='Add Many')
table1 = ttk.TTkTable(parent=frame, selectColor=ttk.TTkColor.bg('#882200'))
table1 = ttk.TTkFancyTable(parent=frame, selectColor=ttk.TTkColor.bg('#882200'))
table1.setColumnSize((5,10,-1,10,20))
table1.setAlignment((
@ -88,7 +88,7 @@ def main():
root = ttk.TTk()
win_table = ttk.TTkWindow(parent=root,pos = (3,3), size=(150,40), title="Test Table 1", layout=ttk.TTkHBoxLayout(), border=True)
demoTable(win_table)
demoFancyTable(win_table)
root.mainloop()
if __name__ == "__main__":

119
demo/showcase/fancytree.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.
# Demo inspired from:
# https://stackoverflow.com/questions/41204234/python-pyqt5-qtreewidget-sub-item
import os
import sys
import random
import argparse
sys.path.append(os.path.join(sys.path[0],'../..'))
import TermTk as ttk
words = ["Lorem", "ipsum", "dolor", "sit", "amet,", "consectetur", "adipiscing", "elit,", "sed", "do", "eiusmod", "tempor", "incididunt", "ut", "labore", "et", "dolore", "magna", "aliqua.", "Ut", "enim", "ad", "minim", "veniam,", "quis", "nostrud", "exercitation", "ullamco", "laboris", "nisi", "ut", "aliquip", "ex", "ea", "commodo", "consequat.", "Duis", "aute", "irure", "dolor", "in", "reprehenderit", "in", "voluptate", "velit", "esse", "cillum", "dolore", "eu", "fugiat", "nulla", "pariatur.", "Excepteur", "sint", "occaecat", "cupidatat", "non", "proident,", "sunt", "in", "culpa", "qui", "officia", "deserunt", "mollit", "anim", "id", "est", "laborum."]
def getWord():
return random.choice(words)
def getSentence(a,b):
return " ".join([getWord() for i in range(0,random.randint(a,b))])
def demoFancyTree(root=None):
# tw = ttk.TTkFancyTreeWidget(parent=rootTree1)
tw = ttk.TTkFancyTree(parent=root)
tw.setHeaderLabels(["Column 1", "Column 2", "Column 3"])
tw.setColumnSize((-1,20,20))
tw.setColumnColors((
ttk.TTkColor.RST,
ttk.TTkColor.fg('#00dddd', modifier=ttk.TTkColorGradient(increment=-4)),
ttk.TTkColor.fg('#cccc00', modifier=ttk.TTkColorGradient(increment=-2))
))
l1 = ttk.TTkFancyTreeWidgetItem(["String A", "String B", "String C"])
l2 = ttk.TTkFancyTreeWidgetItem(["String AA", "String BB", "String CC"])
l3 = ttk.TTkFancyTreeWidgetItem(["String AAA", "String BBB", "String CCC"])
l4 = ttk.TTkFancyTreeWidgetItem(["String AAAA", "String BBBB", "String CCCC"])
l5 = ttk.TTkFancyTreeWidgetItem(["String AAAAA", "String BBBBB", "String CCCCC"])
l2.addChild(l5)
for i in range(3):
l1_child = ttk.TTkFancyTreeWidgetItem(["Child A" + str(i), "Child B" + str(i), "Child C" + str(i)])
l1.addChild(l1_child)
for j in range(2):
l2_child = ttk.TTkFancyTreeWidgetItem(["Child AA" + str(j), "Child BB" + str(j), "Child CC" + str(j)])
l2.addChild(l2_child)
for j in range(2):
l3_child = ttk.TTkFancyTreeWidgetItem(["Child AAA" + str(j), "Child BBB" + str(j), "Child CCC" + str(j)])
l3.addChild(l3_child)
for j in range(2):
l4_child = ttk.TTkFancyTreeWidgetItem(["Child AAAA" + str(j), "Child BBBB" + str(j), "Child CCCC" + str(j)])
l4.addChild(l4_child)
for j in range(2):
l5_child = ttk.TTkFancyTreeWidgetItem(["Child AAAAA" + str(j), "Child BBBBB" + str(j), "Child CCCCC" + str(j)])
l5.addChild(l5_child)
l6 = ttk.TTkFancyTreeWidgetItem(["RND", "RND", "RND"], childIndicatorPolicy=ttk.TTkK.ShowIndicator)
def updateChildren(item):
if item.children(): return
for _ in range(0,random.randint(3,8)):
child = ttk.TTkFancyTreeWidgetItem([getWord(),getWord(),getWord()])
if random.randint(0,10)>5:
child.setChildIndicatorPolicy(ttk.TTkK.ShowIndicator)
child.refreshData.connect(updateChildren)
item.addChild(child)
l6.refreshData.connect(updateChildren)
tw.addTopLevelItem(l1)
tw.addTopLevelItem(l2)
tw.addTopLevelItem(l3)
tw.addTopLevelItem(l4)
tw.addTopLevelItem(l6)
return tw
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-f', help='Full Screen', action='store_true')
args = parser.parse_args()
ttk.TTkLog.use_default_file_logging()
root = ttk.TTk()
if args.f:
rootTree1 = root
root.setLayout(ttk.TTkGridLayout())
else:
rootTree1 = ttk.TTkWindow(parent=root,pos = (0,0), size=(70,40), title="Test Tree 1", layout=ttk.TTkGridLayout(), border=True)
demoFancyTree(rootTree1)
root.mainloop()
if __name__ == "__main__":
main()

16
demo/showcase/tree.py

@ -40,15 +40,9 @@ def getSentence(a,b):
return " ".join([getWord() for i in range(0,random.randint(a,b))])
def demoTree(root=None):
# tw = ttk.TTkTreeWidget(parent=rootTree1)
tw = ttk.TTkTree(parent=root)
tw.setHeaderLabels(["Column 1", "Column 2", "Column 3"])
tw.setColumnSize((20,20,-1))
tw.setColumnColors((
ttk.TTkColor.RST,
ttk.TTkColor.fg('#00dddd', modifier=ttk.TTkColorGradient(increment=-4)),
ttk.TTkColor.fg('#cccc00', modifier=ttk.TTkColorGradient(increment=-2))
))
l1 = ttk.TTkTreeWidgetItem(["String A", "String B", "String C"])
l2 = ttk.TTkTreeWidgetItem(["String AA", "String BB", "String CC"])
l3 = ttk.TTkTreeWidgetItem(["String AAA", "String BBB", "String CCC"])
@ -79,17 +73,17 @@ def demoTree(root=None):
l6 = ttk.TTkTreeWidgetItem(["RND", "RND", "RND"], childIndicatorPolicy=ttk.TTkK.ShowIndicator)
def updateChilds(item):
if item.childs(): return
def updateChildren(item):
if item.children(): return
for _ in range(0,random.randint(3,8)):
child = ttk.TTkTreeWidgetItem([getWord(),getWord(),getWord()])
if random.randint(0,10)>5:
child.setChildIndicatorPolicy(ttk.TTkK.ShowIndicator)
child.refreshData.connect(updateChilds)
child.refreshData.connect(updateChildren)
item.addChild(child)
l6.refreshData.connect(updateChilds)
l6.refreshData.connect(updateChildren)
tw.addTopLevelItem(l1)
tw.addTopLevelItem(l2)

8
docs/MDNotes/TODO.md

@ -93,10 +93,16 @@
- [ ] Basic Implementation
- [ ] Events (Signal/Slots)
- [x] Themes
#### Table Widget
#### Fancy Table Widget
- [x] Basic Implementation
- [ ] Events (Signal/Slots)
- [ ] Themes
#### Tree Widget
- [x] Basic Implementation
- [ ] Implement cache/pagination for big data
- [ ] Events (Signal/Slots)
- [ ] Themes
#### Window Widget
- [x] Basic Implementation
- [ ] Events (Signal/Slots)

6
tests/test.ui.008.table.py → tests/test.ui.008.fancy.table.py

@ -42,13 +42,13 @@ btn1 = ttk.TTkButton(parent=root, pos=(0,0), size=(5,3), border=True, text='Add'
btn2 = ttk.TTkButton(parent=root, pos=(5,0), size=(10,3), border=True, text='Add Many')
win_table1 = ttk.TTkWindow(parent=root,pos = (3,3), size=(150,40), title="Test Table 1", layout=ttk.TTkHBoxLayout(), border=True)
table1 = ttk.TTkTable(parent=win_table1, selectColor=ttk.TTkColor.bg('#882200'))
table1 = ttk.TTkFancyTable(parent=win_table1, selectColor=ttk.TTkColor.bg('#882200'))
win_table2 = ttk.TTkWindow(parent=root,pos = (15,5), size=(100,30), title="Test Table 2 Default", layout=ttk.TTkHBoxLayout(), border=True)
table2 = ttk.TTkTable(parent=win_table2)
table2 = ttk.TTkFancyTable(parent=win_table2)
win_table3 = ttk.TTkWindow(parent=root,pos = (15,5), size=(130,40), title="Test Table 2 Default", layout=ttk.TTkHBoxLayout(), border=True)
table3 = ttk.TTkTable(parent=win_table3, showHeader=False)
table3 = ttk.TTkFancyTable(parent=win_table3, showHeader=False)
table1.setColumnSize((5,10,-1,10,20))
table1.setAlignment((

88
tests/test.ui.011.fancy.tree.py

@ -0,0 +1,88 @@
#!/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.
# Demo inspired from:
# https://stackoverflow.com/questions/41204234/python-pyqt5-qtreewidget-sub-item
import os
import sys
sys.path.append(os.path.join(sys.path[0],'..'))
import TermTk as ttk
ttk.TTkLog.use_default_file_logging()
fullscreen = False
root = ttk.TTk()
if fullscreen:
rootTree1 = root
root.setLayout(ttk.TTkGridLayout())
else:
rootTree1 = ttk.TTkWindow(parent=root,pos = (0,0), size=(150,50), title="Test Tree 1", layout=ttk.TTkGridLayout(), border=True)
# tw = ttk.TTkFancyTreeWidget(parent=rootTree1)
tw = ttk.TTkFancyTree(parent=rootTree1)
tw.setHeaderLabels(["Column 1", "Column 2", "Column 3"])
tw.setColumnSize((20,20,-1))
tw.setColumnColors((
ttk.TTkColor.RST,
ttk.TTkColor.fg('#00dddd', modifier=ttk.TTkColorGradient(increment=-4)),
ttk.TTkColor.fg('#cccc00', modifier=ttk.TTkColorGradient(increment=-2))
))
l1 = ttk.TTkFancyTreeWidgetItem(["String A", "String B", "String C"])
l2 = ttk.TTkFancyTreeWidgetItem(["String AA", "String BB", "String CC"])
l3 = ttk.TTkFancyTreeWidgetItem(["String AAA", "String BBB", "String CCC"])
l4 = ttk.TTkFancyTreeWidgetItem(["String AAAA", "String BBBB", "String CCCC"])
l5 = ttk.TTkFancyTreeWidgetItem(["String AAAAA", "String BBBBB", "String CCCCC"])
l2.addChild(l5)
for i in range(3):
l1_child = ttk.TTkFancyTreeWidgetItem(["Child A" + str(i), "Child B" + str(i), "Child C" + str(i)])
l1.addChild(l1_child)
for j in range(2):
l2_child = ttk.TTkFancyTreeWidgetItem(["Child AA" + str(j), "Child BB" + str(j), "Child CC" + str(j)])
l2.addChild(l2_child)
for j in range(2):
l3_child = ttk.TTkFancyTreeWidgetItem(["Child AAA" + str(j), "Child BBB" + str(j), "Child CCC" + str(j)])
l3.addChild(l3_child)
for j in range(2):
l4_child = ttk.TTkFancyTreeWidgetItem(["Child AAAA" + str(j), "Child BBBB" + str(j), "Child CCCC" + str(j)])
l4.addChild(l4_child)
for j in range(2):
l5_child = ttk.TTkFancyTreeWidgetItem(["Child AAAAA" + str(j), "Child BBBBB" + str(j), "Child CCCCC" + str(j)])
l5.addChild(l5_child)
tw.addTopLevelItem(l1)
tw.addTopLevelItem(l2)
tw.addTopLevelItem(l3)
tw.addTopLevelItem(l4)
root.mainloop()

19
tests/test.ui.011.tree.py

@ -27,30 +27,27 @@
import os
import sys
import argparse
sys.path.append(os.path.join(sys.path[0],'..'))
import TermTk as ttk
ttk.TTkLog.use_default_file_logging()
fullscreen = False
parser = argparse.ArgumentParser()
parser.add_argument('-f', help='Full Screen', action='store_true')
args = parser.parse_args()
root = ttk.TTk()
if fullscreen:
if args.f:
rootTree1 = root
root.setLayout(ttk.TTkGridLayout())
else:
rootTree1 = ttk.TTkWindow(parent=root,pos = (0,0), size=(150,50), title="Test Tree 1", layout=ttk.TTkGridLayout(), border=True)
rootTree1 = ttk.TTkWindow(parent=root,pos = (0,0), size=(150,40), title="Test Tree 1", layout=ttk.TTkGridLayout(), border=True)
# tw = ttk.TTkTreeWidget(parent=rootTree1)
tw = ttk.TTkTree(parent=rootTree1)
tw.setHeaderLabels(["Column 1", "Column 2", "Column 3"])
tw.setColumnSize((20,20,-1))
tw.setColumnColors((
ttk.TTkColor.RST,
ttk.TTkColor.fg('#00dddd', modifier=ttk.TTkColorGradient(increment=-4)),
ttk.TTkColor.fg('#cccc00', modifier=ttk.TTkColorGradient(increment=-2))
))
l1 = ttk.TTkTreeWidgetItem(["String A", "String B", "String C"])
l2 = ttk.TTkTreeWidgetItem(["String AA", "String BB", "String CC"])
l3 = ttk.TTkTreeWidgetItem(["String AAA", "String BBB", "String CCC"])
@ -84,5 +81,7 @@ tw.addTopLevelItem(l1)
tw.addTopLevelItem(l2)
tw.addTopLevelItem(l3)
tw.addTopLevelItem(l4)
l1.setExpanded(True)
l3.setExpanded(True)
root.mainloop()
Loading…
Cancel
Save