Browse Source

Merge branch 'main' of github.com:ceccopierangiolieugenio/pyTermTk into main

pull/18/head
Eugenio Parodi 4 years ago
parent
commit
c36ecc1b32
  1. 7
      TermTk/TTkCore/constant.py
  2. 8
      TermTk/TTkCore/string.py
  3. 2
      TermTk/TTkGui/draw_ascii.py
  4. 2
      TermTk/TTkGui/draw_utf8.py
  5. 18
      TermTk/TTkWidgets/TTkPickers/filepicker.py
  6. 43
      TermTk/TTkWidgets/treewidget.py
  7. 40
      TermTk/TTkWidgets/treewidgetitem.py

7
TermTk/TTkCore/constant.py

@ -113,6 +113,13 @@ class TTkConstant:
DontShowIndicator = ChildIndicatorPolicy.DontShowIndicator
DontShowIndicatorWhenChildless = ChildIndicatorPolicy.DontShowIndicatorWhenChildless
class SortOrder:
AscendingOrder = 0x00
DescendingOrder = 0x01
AscendingOrder = SortOrder.AscendingOrder
DescendingOrder = SortOrder.DescendingOrder
NoInsert = InsertPolicy.NoInsert
InsertAtTop = InsertPolicy.InsertAtTop
# InsertAtCurrent = InsertPolicy.InsertAtCurrent

8
TermTk/TTkCore/string.py

@ -72,6 +72,14 @@ class TTkString():
def __getitem__(self, index):
raise NotImplementedError()
# Operators
def __lt__(self, other): return self._text < other._text
def __le__(self, other): return self._text <= other._text
def __eq__(self, other): return self._text == other._text
def __ne__(self, other): return self._text != other._text
def __gt__(self, other): return self._text > other._text
def __ge__(self, other): return self._text >= other._text
def toAscii(self):
return self._text

2
TermTk/TTkGui/draw_ascii.py

@ -81,7 +81,7 @@ class TTkTheme():
vscroll = ('^','|','X','v')
tree = (' ','+','-',' ',
'|','|')
'|','|','v','^',)
# 0 1 2 3 4 5

2
TermTk/TTkGui/draw_utf8.py

@ -132,7 +132,7 @@ class TTkTheme():
vscroll = ('','','','')
tree = ('','','',' ',
'','')
'','','','')
# 0 1 2 3 4 5

18
TermTk/TTkWidgets/TTkPickers/filepicker.py

@ -66,13 +66,17 @@ class _FileTreeWidgetItem(TTkTreeWidgetItem):
FILE = 0x00
DIR = 0x01
__slots__ = ('_path', '_type')
__slots__ = ('_path', '_type', '_raw')
def __init__(self, *args, **kwargs):
TTkTreeWidgetItem.__init__(self, *args, **kwargs)
self._path = kwargs.get('path', '.')
self._type = kwargs.get('type', _FileTreeWidgetItem.FILE)
self._raw = kwargs.get('raw')
self.setTextAlignment(1, TTkK.RIGHT_ALIGN)
def sortData(self, col):
return self._raw[col]
def path(self):
return self._path
@ -279,14 +283,14 @@ class TTkFileDialogPicker(TTkWindow):
size = f"{info.st_size/1024:.2f} KB"
else:
size = f"{info.st_size} bytes"
return time, size
return time, size, info.st_ctime, info.st_size
if os.path.isdir(nodePath):
if os.path.exists(nodePath):
time, _ = _getStat(nodePath)
time, _, rawTime, _ = _getStat(nodePath)
color = TTkCfg.theme.folderNameColor
else:
time, _ = ""
time, _, rawTime, _ = ""
color = TTkCfg.theme.failNameColor
if os.path.islink(nodePath):
@ -298,6 +302,7 @@ class TTkFileDialogPicker(TTkWindow):
ret.append(_FileTreeWidgetItem(
[ name, "", typef, time],
raw = [ n , -1 , typef , rawTime ],
path=nodePath,
type=_FileTreeWidgetItem.DIR,
icon=TTkString() + TTkCfg.theme.folderIconColor + TTkCfg.theme.fileIcon.folderClose + TTkColor.RST,
@ -305,7 +310,7 @@ class TTkFileDialogPicker(TTkWindow):
elif os.path.isfile(nodePath) or os.path.islink(nodePath):
if os.path.exists(nodePath):
time, size = _getStat(nodePath)
time, size, rawTime, rawSize = _getStat(nodePath)
if os.access(nodePath, os.X_OK):
color = TTkCfg.theme.executableColor
typef="Exec"
@ -313,7 +318,7 @@ class TTkFileDialogPicker(TTkWindow):
color = TTkCfg.theme.fileNameColor
typef="File"
else:
time, size = "", ""
time, size, rawTime, rawSize = "", "", 0, 0
color = TTkCfg.theme.failNameColor
typef="Broken"
@ -327,6 +332,7 @@ class TTkFileDialogPicker(TTkWindow):
if ext: ext = f"{ext[1:]} "
ret.append(_FileTreeWidgetItem(
[ name, size, typef, time],
raw = [ n , rawSize , typef , rawTime ],
path=nodePath,
type=_FileTreeWidgetItem.FILE,
icon=TTkString() + TTkCfg.theme.fileIconColor + TTkCfg.theme.fileIcon.getIcon(n) + TTkColor.RST,

43
TermTk/TTkWidgets/treewidget.py

@ -33,9 +33,10 @@ from TermTk.TTkCore.signal import pyTTkSignal, pyTTkSlot
from dataclasses import dataclass
class TTkTreeWidget(TTkAbstractScrollView):
__slots__ = ( '_items', '_header', '_columnsPos', '_cache',
__slots__ = ( '_rootItem', '_header', '_columnsPos', '_cache',
'_selectedId', '_selected', '_separatorSelected', '_mouseDelta',
'_headerColor', '_selectedColor', '_lineColor',
'_sortColumn', '_sortOrder',
# Signals
'itemChanged', 'itemClicked', 'itemDoubleClicked', 'itemExpanded', 'itemCollapsed', 'itemActivated'
)
@ -59,20 +60,24 @@ class TTkTreeWidget(TTkAbstractScrollView):
self._selected = None
self._selectedId = None
self._separatorSelected = None
self._items = []
self._header = kwargs.get('header',[])
self._columnsPos = []
self._cache = []
self._sortColumn = -1
self._sortOrder = TTkK.AscendingOrder
self._headerColor = kwargs.get('headerColor', TTkCfg.theme.treeHeaderColor)
self._selectedColor = kwargs.get('selectedColor', TTkCfg.theme.treeSelectedColor)
self._lineColor = kwargs.get('lineColor', TTkCfg.theme.treeLineColor)
self.setMinimumHeight(1)
self.setFocusPolicy(TTkK.ClickFocus)
self._rootItem = None
self.clear()
# Overridden function
def viewFullAreaSize(self) -> (int, int):
w = self._columnsPos[-1]+1 if self._columnsPos else 0
h = 1+sum([c.size() for c in self._items])
h = self._rootItem.size()
# TTkLog.debug(f"{w=} {h=}")
return w,h
@ -82,16 +87,16 @@ class TTkTreeWidget(TTkAbstractScrollView):
return self.size()
def clear(self):
for item in self._items:
item.dataChanged.disconnect(self._refreshCache)
self._items = []
if self._rootItem:
self._rootItem.dataChanged.disconnect(self._refreshCache)
self._rootItem = TTkTreeWidgetItem(expanded=True)
self._rootItem.dataChanged.connect(self._refreshCache)
self._refreshCache()
self.viewChanged.emit()
self.update()
def addTopLevelItem(self, item):
item.dataChanged.connect(self._refreshCache)
self._items.append(item)
self._rootItem.addChild(item)
self._refreshCache()
self.viewChanged.emit()
self.update()
@ -103,6 +108,16 @@ class TTkTreeWidget(TTkAbstractScrollView):
self.viewChanged.emit()
self.update()
def sortColumn(self):
'''Returns the column used to sort the contents of the widget.'''
return self._sortColumn
def sortItems(self, col, order):
'''Sorts the items in the widget in the specified order by the values in the given column.'''
self._sortColumn = col
self._sortOrder = order
self._rootItem.sortChildren(col, order)
def mouseDoubleClickEvent(self, evt):
x,y = evt.x, evt.y
ox, oy = self.getViewOffsets()
@ -149,8 +164,15 @@ class TTkTreeWidget(TTkAbstractScrollView):
if y == 0:
for i, c in enumerate(self._columnsPos):
if x == c:
# I-th separator selected
self._separatorSelected = i
self.update()
break
elif x < c:
# I-th header selected
order = not self._sortOrder if self._sortColumn == i else TTkK.AscendingOrder
self.sortItems(i, order)
break
return True
# Handle Tree/Table Events
y += oy-1
@ -240,7 +262,7 @@ class TTkTreeWidget(TTkAbstractScrollView):
if _child.isExpanded():
for _c in _child.children():
_addToCache(_c, _level+1)
for c in self._items:
for c in self._rootItem.children():
_addToCache(c,0)
self.update()
self.viewChanged.emit()
@ -255,6 +277,9 @@ class TTkTreeWidget(TTkAbstractScrollView):
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)
if i == self._sortColumn:
s = tt[6] if self._sortOrder == TTkK.AscendingOrder else tt[7]
self._canvas.drawText(pos=(hx1-x-1,0), text=s, color=self._headerColor)
# Draw header separators
for sx in self._columnsPos:
self._canvas.drawChar(pos=(sx-x,0), char=tt[5], color=self._headerColor)

40
TermTk/TTkWidgets/treewidgetitem.py

@ -31,7 +31,8 @@ from TermTk.TTkAbstract.abstractitemmodel import TTkAbstractItemModel
class TTkTreeWidgetItem(TTkAbstractItemModel):
__slots__ = ('_parent', '_data', '_alignment', '_children', '_expanded', '_selected',
'_childIndicatorPolicy', '_icon', '_defaultIcon'
'_childIndicatorPolicy', '_icon', '_defaultIcon',
'_sortColumn', '_sortOrder'
# Signals
# 'refreshData'
)
@ -42,16 +43,19 @@ class TTkTreeWidgetItem(TTkAbstractItemModel):
tt = TTkCfg.theme.tree
super().__init__(self, *args, **kwargs)
self._children = []
self._data = args[0] if len(args)>0 and type(args[0])==list else None
self._data = args[0] if len(args)>0 and type(args[0])==list else ['']
self._alignment = [TTkK.LEFT_ALIGN]*len(self._data)
self._parent = kwargs.get('parent', None)
self._childIndicatorPolicy = kwargs.get('childIndicatorPolicy', TTkK.DontShowIndicatorWhenChildless)
self._defaultIcon = True
self._expanded = False
self._selected = False
self._expanded = kwargs.get('expanded', False)
self._selected = kwargs.get('selected', False)
self._parent = kwargs.get("parent", None)
self._sortColumn = -1
self._sortOrder = TTkK.AscendingOrder
self._icon = ['']*len(self._data)
self._setDefaultIcon()
if 'icon' in kwargs:
@ -78,8 +82,11 @@ class TTkTreeWidgetItem(TTkAbstractItemModel):
def addChild(self, child):
self._children.append(child)
child._parent = self
child.dataChanged.connect(self.emitDataChanged)
child._sortOrder = self._sortOrder
child._sortColumn = self._sortColumn
self._setDefaultIcon()
self._sort(children=False)
child.dataChanged.connect(self.emitDataChanged)
self.dataChanged.emit()
def addChildren(self, children):
@ -119,6 +126,29 @@ class TTkTreeWidgetItem(TTkAbstractItemModel):
return ''
return self._data[col]
def sortData(self, col):
return self.data(col)
def _sort(self, children):
if self._sortColumn == -1: return
self._children = sorted(
self._children,
key = lambda x : x.sortData(self._sortColumn),
reverse = self._sortOrder == TTkK.DescendingOrder)
# Broadcast the sorting to the childrens
if children:
for c in self._children:
c.dataChanged.disconnect(self.emitDataChanged)
c.sortChildren(self._sortColumn, self._sortOrder)
c.dataChanged.connect(self.emitDataChanged)
def sortChildren(self, col, order):
self._sortColumn = col
self._sortOrder = order
if not self._children: return
self._sort(children=True)
self.dataChanged.emit()
@pyTTkSlot()
def emitDataChanged(self):
self.dataChanged.emit()

Loading…
Cancel
Save