Browse Source

386 feat ttktree add drag (#387)

pull/385/head^2
Pier CeccoPierangioliEugenio 11 months ago committed by GitHub
parent
commit
62f9cd42a6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 7
      libs/pyTermTk/TermTk/TTkCore/TTkTerm/inputmouse.py
  2. 18
      libs/pyTermTk/TermTk/TTkGui/drag.py
  3. 1
      libs/pyTermTk/TermTk/TTkWidgets/TTkModelView/tree.py
  4. 38
      libs/pyTermTk/TermTk/TTkWidgets/TTkModelView/treewidget.py
  5. 90
      libs/pyTermTk/TermTk/TTkWidgets/kodetab.py
  6. 92
      libs/pyTermTk/TermTk/TTkWidgets/tabwidget.py
  7. 13
      libs/pyTermTk/TermTk/TTkWidgets/widget.py
  8. 135
      tests/t.ui/test.ui.011.tree.04.dnd.01.py

7
libs/pyTermTk/TermTk/TTkCore/TTkTerm/inputmouse.py

@ -86,6 +86,13 @@ class TTkMouseEvent:
Right = TTkK.WHEEL_Right Right = TTkK.WHEEL_Right
__slots__ = ('x', 'y', 'key', 'evt', 'mod', 'tap', 'raw') __slots__ = ('x', 'y', 'key', 'evt', 'mod', 'tap', 'raw')
x: int
y: int
key: int
evt: int
mod: int
tap: int
raw: str
def __init__(self, x: int, y: int, key: int, evt: int, mod: int, tap: int, raw: str): def __init__(self, x: int, y: int, key: int, evt: int, mod: int, tap: int, raw: str):
self.x = x self.x = x
self.y = y self.y = y

18
libs/pyTermTk/TermTk/TTkGui/drag.py

@ -100,6 +100,15 @@ class TTkDnD():
''' '''
return self._hotSpot return self._hotSpot
def clone(self):
'''
Clone this event
:return: the cloned event
:rtype: :py:class:`TTkDnD`
'''
return TTkDnD(data=self._data, hotspot=self._hotSpot)
class TTkDnDEvent(TTkDnD): class TTkDnDEvent(TTkDnD):
''' '''
Drag and Drop event class. Drag and Drop event class.
@ -123,6 +132,15 @@ class TTkDnDEvent(TTkDnD):
''' '''
return self._pos return self._pos
def clone(self):
'''
Clone this event
:return: the cloned event
:rtype: :py:class:`TTkDnDEvent`
'''
return TTkDnDEvent(data=self._data, hotspot=self._hotSpot, pos=self._pos)
class TTkDrag(TTkDnD): class TTkDrag(TTkDnD):
__slots__ = ('_pixmap', '_showPixmap') __slots__ = ('_pixmap', '_showPixmap')
def __init__(self, **kwargs) -> None: def __init__(self, **kwargs) -> None:

1
libs/pyTermTk/TermTk/TTkWidgets/TTkModelView/tree.py

@ -41,6 +41,7 @@ class TTkTree(TTkAbstractScrollArea):
'setHeaderLabels', 'setHeaderLabels',
'setColumnWidth', 'resizeColumnToContents', 'setColumnWidth', 'resizeColumnToContents',
'sortColumn', 'sortItems', 'sortColumn', 'sortItems',
'dragDropMode', 'setDragDropMode',
# 'appendItem', 'setAlignment', 'setColumnColors', 'setColumnSize', 'setHeader', # 'appendItem', 'setAlignment', 'setColumnColors', 'setColumnSize', 'setHeader',
'addTopLevelItem', 'addTopLevelItems', 'takeTopLevelItem', 'topLevelItem', 'indexOfTopLevelItem', 'selectedItems', 'clear']) 'addTopLevelItem', 'addTopLevelItems', 'takeTopLevelItem', 'topLevelItem', 'indexOfTopLevelItem', 'selectedItems', 'clear'])
) )

38
libs/pyTermTk/TermTk/TTkWidgets/TTkModelView/treewidget.py

@ -22,14 +22,19 @@
__all__ = ['TTkTreeWidget'] __all__ = ['TTkTreeWidget']
from typing import List
from TermTk.TTkCore.cfg import TTkCfg from TermTk.TTkCore.cfg import TTkCfg
from TermTk.TTkCore.constant import TTkK from TermTk.TTkCore.constant import TTkK
from TermTk.TTkCore.color import TTkColor from TermTk.TTkCore.color import TTkColor
from TermTk.TTkCore.string import TTkString from TermTk.TTkCore.string import TTkString
from TermTk.TTkCore.canvas import TTkCanvas
from TermTk.TTkCore.TTkTerm.inputmouse import TTkMouseEvent from TermTk.TTkCore.TTkTerm.inputmouse import TTkMouseEvent
from TermTk.TTkGui.drag import TTkDrag, TTkDnDEvent
from TermTk.TTkWidgets.TTkModelView.treewidgetitem import TTkTreeWidgetItem from TermTk.TTkWidgets.TTkModelView.treewidgetitem import TTkTreeWidgetItem
from TermTk.TTkAbstract.abstractscrollview import TTkAbstractScrollView from TermTk.TTkAbstract.abstractscrollview import TTkAbstractScrollView
from TermTk.TTkAbstract.abstractitemmodel import TTkAbstractItemModel
from TermTk.TTkCore.signal import pyTTkSignal, pyTTkSlot from TermTk.TTkCore.signal import pyTTkSignal, pyTTkSlot
from dataclasses import dataclass from dataclasses import dataclass
@ -151,6 +156,7 @@ class TTkTreeWidget(TTkAbstractScrollView):
'_header', '_columnsPos', '_header', '_columnsPos',
'_selectedId', '_selected', '_separatorSelected', '_selectedId', '_selected', '_separatorSelected',
'_sortColumn', '_sortOrder', '_sortingEnabled', '_sortColumn', '_sortOrder', '_sortingEnabled',
'_dndMode',
# Signals # Signals
'itemChanged', 'itemClicked', 'itemDoubleClicked', 'itemExpanded', 'itemCollapsed', 'itemActivated' 'itemChanged', 'itemClicked', 'itemDoubleClicked', 'itemExpanded', 'itemCollapsed', 'itemActivated'
) )
@ -162,15 +168,23 @@ class TTkTreeWidget(TTkAbstractScrollView):
widgets: list widgets: list
firstLine: bool firstLine: bool
@dataclass(frozen=True)
class _DropTreeData:
widget: TTkAbstractScrollView
items: List[TTkAbstractItemModel]
def __init__(self, *, def __init__(self, *,
header=None, header=None,
sortingEnabled=True, sortingEnabled=True,
dragDropMode:TTkK.DragDropMode=TTkK.DragDropMode.NoDragDrop,
**kwargs) -> None: **kwargs) -> None:
''' '''
:param header: define the header labels of each column, defaults to [] :param header: define the header labels of each column, defaults to []
:type header: list[TTkString], optional :type header: list[TTkString], optional
:param sortingEnabled: enable the column sorting, defaults to False :param sortingEnabled: enable the column sorting, defaults to False
:type sortingEnabled: bool, optional :type sortingEnabled: bool, optional
:param dragDropMode: This property holds the drag and drop event the view will act upon, defaults to :py:class:`TTkK.DragDropMode.NoDragDrop`.
:type dragDropMode: :py:class:`TTkK.DragDropMode`, optional
''' '''
# Signals # Signals
self.itemActivated = pyTTkSignal(TTkTreeWidgetItem, int) self.itemActivated = pyTTkSignal(TTkTreeWidgetItem, int)
@ -180,6 +194,7 @@ class TTkTreeWidget(TTkAbstractScrollView):
self.itemExpanded = pyTTkSignal(TTkTreeWidgetItem) self.itemExpanded = pyTTkSignal(TTkTreeWidgetItem)
self.itemCollapsed = pyTTkSignal(TTkTreeWidgetItem) self.itemCollapsed = pyTTkSignal(TTkTreeWidgetItem)
self._dndMode = dragDropMode
self._selected = None self._selected = None
self._selectedId = None self._selectedId = None
self._separatorSelected = None self._separatorSelected = None
@ -270,6 +285,14 @@ class TTkTreeWidget(TTkAbstractScrollView):
self.viewChanged.emit() self.viewChanged.emit()
self.update() self.update()
def dragDropMode(self):
'''dragDropMode'''
return self._dndMode
def setDragDropMode(self, dndMode):
'''setDragDropMode'''
self._dndMode = dndMode
def isSortingEnabled(self) -> bool: def isSortingEnabled(self) -> bool:
'isSortingEnabled' 'isSortingEnabled'
return self._sortingEnabled return self._sortingEnabled
@ -432,6 +455,21 @@ class TTkTreeWidget(TTkAbstractScrollView):
self.viewChanged.emit() self.viewChanged.emit()
self.update() self.update()
return True return True
elif ( self._dndMode & TTkK.DragDropMode.AllowDrag and
evt.key == TTkMouseEvent.LeftButton and self._selected ):
drag = TTkDrag()
data = TTkTreeWidget._DropTreeData(widget=self,items=[self._selected])
text = self._selected.data(0)
if text.termWidth() > 30:
text = '['+text.substring(to=27)+'...]'
else:
text = '['+text+']'
pm = TTkCanvas(text.termWidth()+2,1)
pm.drawTTkString(pos=(0,0),text=text)
drag.setPixmap(pm)
drag.setData(data)
drag.exec()
return True
return False return False
def _alignWidgets(self) -> None: def _alignWidgets(self) -> None:

90
libs/pyTermTk/TermTk/TTkWidgets/kodetab.py

@ -22,6 +22,8 @@
__all__ = ['TTkKodeTab'] __all__ = ['TTkKodeTab']
from typing import Callable
from TermTk.TTkCore.constant import TTkK from TermTk.TTkCore.constant import TTkK
from TermTk.TTkCore.helper import TTkHelper from TermTk.TTkCore.helper import TTkHelper
from TermTk.TTkCore.log import TTkLog from TermTk.TTkCore.log import TTkLog
@ -29,7 +31,7 @@ from TermTk.TTkCore.string import TTkString
from TermTk.TTkCore.color import TTkColor, TTkColorGradient from TermTk.TTkCore.color import TTkColor, TTkColorGradient
from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal
from TermTk.TTkWidgets.widget import TTkWidget from TermTk.TTkWidgets.widget import TTkWidget
from TermTk.TTkWidgets.tabwidget import TTkTabWidget from TermTk.TTkWidgets.tabwidget import TTkTabWidget, _TTkNewTabWidgetDragData, _TTkTabWidgetDragData
from TermTk.TTkWidgets.splitter import TTkSplitter from TermTk.TTkWidgets.splitter import TTkSplitter
from TermTk.TTkWidgets.frame import TTkFrame from TermTk.TTkWidgets.frame import TTkFrame
from TermTk.TTkLayouts.gridlayout import TTkGridLayout from TermTk.TTkLayouts.gridlayout import TTkGridLayout
@ -117,45 +119,78 @@ class _TTkKodeTab(TTkTabWidget):
def dropEvent(self, evt:TTkDnDEvent) -> bool: def dropEvent(self, evt:TTkDnDEvent) -> bool:
self._frameOverlay = None self._frameOverlay = None
x,y = evt.x, evt.y x,y = evt.x, evt.y
ret = True
data = evt.data() data = evt.data()
tb = data.tabButton() if issubclass(type(data),_TTkNewTabWidgetDragData):
tw = data.tabWidget() tw = None
elif issubclass(type(data),_TTkTabWidgetDragData):
tw = data.tabWidget()
else:
return False
def _processDrop(widget, label, orientation, offset):
fwold = self._baseWidget._getFirstWidget()
splitter = self.parentWidget()
index = splitter.indexOf(self)
if splitter.orientation() != orientation:
splitter.replaceWidget(index, splitter := TTkSplitter(orientation=orientation))
splitter.addWidget(self)
index=offset
splitter.insertWidget(index+offset, kt:=_TTkKodeTab(baseWidget=self._baseWidget, border=self.border(), closable=self.tabsClosable()))
kt._dropEventProxy = self._dropEventProxy
kt.addTab(widget,label)
if fwold!=(fwnew := self._baseWidget._getFirstWidget()) and fwold._hasMenu():
fwnew._importMenu(fwold)
ret = True
if y<3: if y<3:
ret = super().dropEvent(evt) ret = super().dropEvent(evt)
else: elif issubclass(type(data),_TTkNewTabWidgetDragData):
tw = None
widget = data.widget()
tabData = data.data()
label = data.label()
closable = data.closable()
w,h = self.size()
h-=3
y-=3
if x<w//4:
_processDrop(widget, label, TTkK.HORIZONTAL, 0)
elif x>w*3//4:
_processDrop(widget, label, TTkK.HORIZONTAL, 1)
elif y<h//4:
_processDrop(widget, label, TTkK.VERTICAL, 0)
elif y>h*3//4:
_processDrop(widget, label, TTkK.VERTICAL, 1)
else:
ret = super().dropEvent(evt)
elif issubclass(type(data),_TTkTabWidgetDragData):
tb = data.tabButton()
tw = data.tabWidget()
w,h = self.size() w,h = self.size()
h-=3 h-=3
y-=3 y-=3
index = tw._tabBar._tabButtons.index(tb) index = tw._tabBar._tabButtons.index(tb)
widget = tw._tabWidgets[index] widget = tw._tabWidgets[index]
label = tb.text()
def _processDrop(index, orientation, offset):
fwold = self._baseWidget._getFirstWidget()
tw.removeTab(index)
splitter = self.parentWidget()
index = splitter.indexOf(self)
if splitter.orientation() != orientation:
splitter.replaceWidget(index, splitter := TTkSplitter(orientation=orientation))
splitter.addWidget(self)
index=offset
splitter.insertWidget(index+offset, kt:=_TTkKodeTab(baseWidget=self._baseWidget, border=self.border(), closable=self.tabsClosable()))
kt.addTab(widget,tb.text())
if fwold!=(fwnew := self._baseWidget._getFirstWidget()) and fwold._hasMenu():
fwnew._importMenu(fwold)
if x<w//4: if x<w//4:
_processDrop(index, TTkK.HORIZONTAL, 0) tw.removeTab(index)
_processDrop(widget, label, TTkK.HORIZONTAL, 0)
elif x>w*3//4: elif x>w*3//4:
_processDrop(index, TTkK.HORIZONTAL, 1) tw.removeTab(index)
_processDrop(widget, label, TTkK.HORIZONTAL, 1)
elif y<h//4: elif y<h//4:
_processDrop(index, TTkK.VERTICAL, 0) tw.removeTab(index)
_processDrop(widget, label, TTkK.VERTICAL, 0)
elif y>h*3//4: elif y>h*3//4:
_processDrop(index, TTkK.VERTICAL, 1) tw.removeTab(index)
_processDrop(widget, label, TTkK.VERTICAL, 1)
else: else:
ret = super().dropEvent(evt) ret = super().dropEvent(evt)
# Remove the widget and/or all the cascade empty splitters # Remove the widget and/or all the cascade empty splitters
self._kodeTabClosed(tw) if tw:
self._kodeTabClosed(tw)
self.update() self.update()
return ret return ret
@ -163,7 +198,7 @@ class _TTkKodeTab(TTkTabWidget):
def _kodeTabClosed(self, widget=None): def _kodeTabClosed(self, widget=None):
# Remove the widget and/or all the cascade empty splitters # Remove the widget and/or all the cascade empty splitters
fwold = self._baseWidget._getFirstWidget() fwold = self._baseWidget._getFirstWidget()
widget = widget if type(widget) is _TTkKodeTab else self widget = widget if issubclass(type(widget), _TTkKodeTab) else self
if not widget._tabWidgets: if not widget._tabWidgets:
if splitter := widget.parentWidget(): if splitter := widget.parentWidget():
while splitter.count() == 1 and splitter != self._baseWidget: while splitter.count() == 1 and splitter != self._baseWidget:
@ -199,6 +234,7 @@ class TTkKodeTab(TTkSplitter):
kwargs.pop('visible',None) kwargs.pop('visible',None)
# self.layout().addWidget(splitter := TTkSplitter()) # self.layout().addWidget(splitter := TTkSplitter())
self._lastKodeTabWidget = _TTkKodeTab(baseWidget=self, **kwargs) self._lastKodeTabWidget = _TTkKodeTab(baseWidget=self, **kwargs)
self._lastKodeTabWidget._dropEventProxy = self._dropEventProxy
self.addWidget(self._lastKodeTabWidget) self.addWidget(self._lastKodeTabWidget)
def _getFirstWidget(self): def _getFirstWidget(self):
@ -207,6 +243,12 @@ class TTkKodeTab(TTkSplitter):
while type(item:=kt.widget(0)) != _TTkKodeTab: kt = item while type(item:=kt.widget(0)) != _TTkKodeTab: kt = item
return item if type(item)==_TTkKodeTab else None return item if type(item)==_TTkKodeTab else None
def setDropEventProxy(self, proxy:Callable) -> None:
for widget in self.layout().iterWidgets(onlyVisible=False):
if issubclass(type(widget),_TTkKodeTab):
widget.setDropEventProxy(proxy)
return super().setDropEventProxy(proxy)
@pyTTkSlot(TTkWidget) @pyTTkSlot(TTkWidget)
def setCurrentWidget(self, *args, **kwargs) -> None: def setCurrentWidget(self, *args, **kwargs) -> None:
return self._lastKodeTabWidget.setCurrentWidget(*args, **kwargs) return self._lastKodeTabWidget.setCurrentWidget(*args, **kwargs)

92
libs/pyTermTk/TermTk/TTkWidgets/tabwidget.py

@ -65,7 +65,6 @@ _tabStyleFocussed = {
} }
class _TTkTabWidgetDragData(): class _TTkTabWidgetDragData():
__slots__ = ('_tabButton', '_tabWidget') __slots__ = ('_tabButton', '_tabWidget')
def __init__(self, b, tw): def __init__(self, b, tw):
self._tabButton = b self._tabButton = b
@ -73,6 +72,18 @@ class _TTkTabWidgetDragData():
def tabButton(self): return self._tabButton def tabButton(self): return self._tabButton
def tabWidget(self): return self._tabWidget def tabWidget(self): return self._tabWidget
class _TTkNewTabWidgetDragData():
__slots__ = ('_label', '_widget', '_closable', '_data')
def __init__(self, label, widget:TTkWidget, data=None, closable:bool=False):
self._data = data
self._label = label
self._widget = widget
self._closable = closable
def data(self): return self._data
def label(self): return self._label
def widget(self): return self._widget
def closable(self): return self._closable
class _TTkTabBarDragData(): class _TTkTabBarDragData():
__slots__ = ('_tabButton','_tabBar') __slots__ = ('_tabButton','_tabBar')
def __init__(self, b, tb): def __init__(self, b, tb):
@ -666,37 +677,54 @@ class TTkTabWidget(TTkFrame):
def dropEvent(self, evt:TTkDnDEvent) -> bool: def dropEvent(self, evt:TTkDnDEvent) -> bool:
data = evt.data() data = evt.data()
x, y = evt.x, evt.y x, y = evt.x, evt.y
if not issubclass(type (data),_TTkTabWidgetDragData): if issubclass(type(data),_TTkTabWidgetDragData):
return False tb = data.tabButton()
tb = data.tabButton() tw = data.tabWidget()
tw = data.tabWidget() index = tw._tabBar._tabButtons.index(tb)
index = tw._tabBar._tabButtons.index(tb) widget = tw.widget(index)
widget = tw.widget(index) data = tw.tabData(index)
data = tw.tabData(index) if TTkHelper.isParent(self, tw):
if TTkHelper.isParent(self, tw): return False
return False if y < 3:
if y < 3: tbx = self._tabBar.x()
tbx = self._tabBar.x() newIndex = 0
newIndex = 0 for b in self._tabBar._tabButtons:
for b in self._tabBar._tabButtons: if tbx+b.x()+b.width()/2 < x:
if tbx+b.x()+b.width()/2 < x: newIndex += 1
newIndex += 1 if tw == self:
if tw == self: if index <= newIndex:
if index <= newIndex: newIndex -= 1
newIndex -= 1 tw.removeTab(index)
tw.removeTab(index) self.insertTab(newIndex, widget, tb.text(), data, tb._closable)
self.insertTab(newIndex, widget, tb.text(), data, tb._closable) self.setCurrentIndex(newIndex)
self.setCurrentIndex(newIndex) #self._tabChanged(newIndex)
#self._tabChanged(newIndex) elif tw != self:
elif tw != self: tw.removeTab(index)
tw.removeTab(index) newIndex = len(self._tabWidgets)
newIndex = len(self._tabWidgets) self.addTab(widget, tb.text(), data)
self.addTab(widget, tb.text(), data) self.setCurrentIndex(newIndex)
self.setCurrentIndex(newIndex) self._tabChanged(newIndex)
self._tabChanged(newIndex) TTkLog.debug(f"Drop -> pos={evt.pos()}")
return True
TTkLog.debug(f"Drop -> pos={evt.pos()}") elif issubclass(type(data),_TTkNewTabWidgetDragData):
return True w = data.widget()
d = data.data()
l = data.label()
c = data.closable()
if y < 3:
tbx = self._tabBar.x()
newIndex = 0
for b in self._tabBar._tabButtons:
if tbx+b.x()+b.width()/2 < x:
newIndex += 1
self.insertTab(newIndex, w, l, d, c)
self.setCurrentIndex(newIndex)
else:
self.addTab(w, l, d, c)
self.setCurrentIndex(len(self._tabBar._tabButtons)-1)
TTkLog.debug(f"Drop -> pos={evt.pos()}")
return True
return False
def addMenu(self, text, position=TTkK.LEFT, data=None) -> TTkMenuBarButton: def addMenu(self, text, position=TTkK.LEFT, data=None) -> TTkMenuBarButton:
'''addMenu''' '''addMenu'''

13
libs/pyTermTk/TermTk/TTkWidgets/widget.py

@ -22,6 +22,8 @@
__all__ = ['TTkWidget'] __all__ = ['TTkWidget']
from typing import Callable, Any, List
try: try:
from typing import Self from typing import Self
except: except:
@ -115,6 +117,7 @@ class TTkWidget(TMouseEvents,TKeyEvents, TDragEvents):
'_enabled', '_enabled',
'_style', '_currentStyle', '_style', '_currentStyle',
'_toolTip', '_toolTip',
'_dropEventProxy',
'_widgetCursor', '_widgetCursorEnabled', '_widgetCursorType', '_widgetCursor', '_widgetCursorEnabled', '_widgetCursorType',
#Signals #Signals
'focusChanged', 'sizeChanged', 'currentStyleChanged', 'closed') 'focusChanged', 'sizeChanged', 'currentStyleChanged', 'closed')
@ -194,6 +197,7 @@ class TTkWidget(TMouseEvents,TKeyEvents, TDragEvents):
self.closed = pyTTkSignal(TTkWidget) self.closed = pyTTkSignal(TTkWidget)
# self.sizeChanged.connect(self.resizeEvent) # self.sizeChanged.connect(self.resizeEvent)
self._dropEventProxy = lambda x:x
self._widgetCursor = (0,0) self._widgetCursor = (0,0)
self._widgetCursorEnabled = False self._widgetCursorEnabled = False
self._widgetCursorType = TTkK.Cursor_Blinking_Bar self._widgetCursorType = TTkK.Cursor_Blinking_Bar
@ -267,6 +271,13 @@ class TTkWidget(TMouseEvents,TKeyEvents, TDragEvents):
''' '''
self._name = name self._name = name
def setDropEventProxy(self, proxy:Callable) -> None:
'''
.. warning::
This is an alpha Method to prototype the Drag and Drop prosy feature and may change in the future
'''
self._dropEventProxy = proxy
def widgetItem(self) -> TTkWidgetItem: def widgetItem(self) -> TTkWidgetItem:
return self._widgetItem return self._widgetItem
@ -444,7 +455,7 @@ class TTkWidget(TMouseEvents,TKeyEvents, TDragEvents):
TTkHelper.dndEnter(self) TTkHelper.dndEnter(self)
return True return True
if evt.evt == TTkK.Release: if evt.evt == TTkK.Release:
if self.dropEvent(TTkHelper.dndGetDrag().getDropEvent(evt)): if self.dropEvent(self._dropEventProxy(TTkHelper.dndGetDrag().getDropEvent(evt))):
return True return True
return ret return ret

135
tests/t.ui/test.ui.011.tree.04.dnd.01.py

@ -0,0 +1,135 @@
#!/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 argparse
sys.path.append(os.path.join(sys.path[0],'../..'))
import TermTk as ttk
class DropClass(ttk.TTkFrame):
def __init__(self, **kwargs):
super().__init__(**kwargs|{'title':'Drop Here'})
def dropEvent(self, evt):
ttk.TTkLog.debug(f"Dropped: {evt.data()}")
return super().dropEvent(evt)
def dragEnterEvent(self, evt):
ttk.TTkLog.debug(f"Drag Enter: {evt}")
return super().dragEnterEvent(evt)
def dragMoveEvent(self, evt):
ttk.TTkLog.debug(f"Drag Move: {evt}")
return super().dragMoveEvent(evt)
def dragLeaveEvent(self, evt):
ttk.TTkLog.debug(f"Drag Leave: {evt}")
return super().dragLeaveEvent(evt)
def dropEventProxy(evt:ttk.TTkDnDEvent):
data = evt.data()
ttk.TTkLog.debug(f"Proxy: {evt=} {data=}")
if issubclass(type(data), ttk.TTkTreeWidget._DropTreeData) and data.items:
item:ttk.TTkTreeWidgetItem = data.items[0]
newData = ttk.TTkWidgets.tabwidget._TTkNewTabWidgetDragData(
widget=ttk.TTkTestWidgetSizes(),
label=item.data(0),
data=None,
closable=True
)
newEvt = evt.clone()
newEvt.setData(newData)
return newEvt
return evt
ttk.TTkLog.use_default_file_logging()
parser = argparse.ArgumentParser()
parser.add_argument('-f', help='Full Screen', action='store_true')
args = parser.parse_args()
root = ttk.TTk()
DropClass(parent=root, pos=(0,0), size=(30,5))
logsWin = ttk.TTkWindow(parent=root, title='Logs', pos=(31,0), size=(100,30), layout=ttk.TTkGridLayout())
ttk.TTkLogViewer(parent=logsWin)
kodeWin = ttk.TTkWindow(parent=root,pos = (30,5), size=(80,40), title="KodeWin", layout=ttk.TTkGridLayout(), border=True)
kt = ttk.TTkKodeTab(parent=kodeWin)
kt.setDropEventProxy(dropEventProxy)
kt.addTab(ttk.TTkTestWidgetSizes(),"t 1")
kt.addTab(ttk.TTkTestWidgetSizes(),"t 2")
kt.addTab(ttk.TTkTestWidgetSizes(),"t 3")
kt.addTab(ttk.TTkTestWidgetSizes(),"t 4")
kt.addTab(ttk.TTkTestWidgetSizes(),"t 5")
fileTreeWin = ttk.TTkWindow(parent=root,pos = (3,12), size=(40,40), title="Test Tree 1", layout=ttk.TTkGridLayout(), border=True)
ft = ttk.TTkFileTree(parent=fileTreeWin, dragDropMode=ttk.TTkK.DragDropMode.AllowDrag)
treeWin = ttk.TTkWindow(parent=root,pos = (0,6), size=(40,40), title="Test Tree 1", layout=ttk.TTkGridLayout(), border=True)
tw = ttk.TTkTree(parent=treeWin, dragDropMode=ttk.TTkK.DragDropMode.AllowDrag)
tw.setHeaderLabels(["Column 1", "Column 2", "Column 3"])
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"])
l4 = ttk.TTkTreeWidgetItem(["String AAAA", "String BBBB", "String CCCC"])
l5 = ttk.TTkTreeWidgetItem(["String AAAAA", "String BBBBB", "String CCCCC"])
l2.addChild(l5)
for i in range(3):
l1_child = ttk.TTkTreeWidgetItem(["Child A" + str(i), "Child B" + str(i), "Child C" + str(i)])
l1.addChild(l1_child)
for j in range(2):
l2_child = ttk.TTkTreeWidgetItem(["Child AA" + str(j), "Child BB" + str(j), "Child CC" + str(j)])
l2.addChild(l2_child)
for j in range(2):
l3_child = ttk.TTkTreeWidgetItem(["Child AAA" + str(j), "Child BBB" + str(j), "Child CCC" + str(j)])
l3.addChild(l3_child)
for j in range(2):
l4_child = ttk.TTkTreeWidgetItem(["Child AAAA" + str(j), "Child BBBB" + str(j), "Child CCCC" + str(j)])
l4.addChild(l4_child)
for j in range(2):
l5_child = ttk.TTkTreeWidgetItem(["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)
l1.setExpanded(True)
l3.setExpanded(True)
root.mainloop()
Loading…
Cancel
Save