Browse Source

Added TableModels Doc

pull/272/head
Eugenio Parodi 1 year ago
parent
commit
ecc38972a8
  1. 35
      TermTk/TTkAbstract/abstracttablemodel.py
  2. 30
      TermTk/TTkWidgets/TTkModelView/tablemodelcsv.py
  3. 39
      TermTk/TTkWidgets/TTkModelView/tablemodellist.py
  4. 6
      TermTk/TTkWidgets/TTkModelView/tablewidget.py
  5. 2
      tests/t.ui/test.ui.032.table.07.py

35
TermTk/TTkAbstract/abstracttablemodel.py

@ -27,7 +27,38 @@ from TermTk.TTkCore.string import TTkString
from TermTk.TTkCore.signal import pyTTkSignal, pyTTkSlot
class TTkAbstractTableModel():
'''TTkAbstractTableModel'''
'''
:class:`TTkAbstractTableModel` provides a standard interface for
models that represent their data as a two-dimensional array of items.
It is not used directly, but must be subclassed.
Since the model provides a more specialized interface than QAbstractItemModel,
it is not suitable for use with tree views, although it can be used to provide data to a QListView.
If you need to represent a simple list of items, and only need a model to contain a single column of data,
subclassing the QAbstractListModel may be more appropriate.
The rowCount() and columnCount() functions return the dimensions of the table.
To retrieve a model index corresponding to an item in the model,
use index() and provide only the row and column numbers.
**Subclassing**
When subclassing QAbstractTableModel, you must implement :meth:`rowCount`, :meth:`columnCount`, and :meth:`data`.
Well behaved models will also implement :meth:`headerData`.
Editable models need to implement :meth:`setData`.
Models that provide interfaces to resizable data structures can provide implementations of
insertRows(), removeRows(), insertColumns(), and removeColumns().
**Built-In Implementation**
:class:`~TermTk.TTkWidgets.TTkModelView.tablemodellist.TTkTableModelList` basic subclass implementing a 2d list as data structure
:class:`~TermTk.TTkWidgets.TTkModelView.tablemodelcsv.TTkTableModelCSV` subclass of :class:`~TermTk.TTkWidgets.TTkModelView.tablemodellist.TTkTableModelList` including the api to import csv data
:class:`~TermTk.TTkWidgets.TTkModelView.tablemodeljson.TTkTableModelJson` subclass of :class:`~TermTk.TTkWidgets.TTkModelView.tablemodellist.TTkTableModelList` with a focus on json data structures
'''
__slots__ = (
# Signals
'dataChanged'
@ -42,7 +73,7 @@ class TTkAbstractTableModel():
raise NotImplementedError()
def data(self, row:int, col:int) -> object:
return TTkString()
raise NotImplementedError()
def ttkStringData(self, row:int, col:int) -> TTkString:
data = self.data(row,col)

30
TermTk/TTkWidgets/TTkModelView/tablemodelcsv.py

@ -28,34 +28,34 @@ from TermTk.TTkCore.constant import TTkK
from TermTk.TTkWidgets.TTkModelView.tablemodellist import TTkTableModelList
class TTkTableModelCSV(TTkTableModelList):
def __init__(self, *, filename='', fd=None):
ml, head, idx = [[]], [], []
def __init__(self, *, filename=None, fd=None):
data, head, idx = [[]], [], []
if filename:
with open(filename, "r") as fd:
ml, head, idx = self._csvImport(fd)
data, head, idx = self._csvImport(fd)
elif fd:
ml, head, idx = self._csvImport(fd)
super().__init__(list=ml,header=head,indexes=idx)
data, head, idx = self._csvImport(fd)
super().__init__(data=data,header=head,indexes=idx)
def _csvImport(self, fd) -> tuple[list,list,list[list]]:
ml, head, idx = [], [], []
data, head, idx = [], [], []
sniffer = csv.Sniffer()
has_header = sniffer.has_header(fd.read(2048))
fd.seek(0)
csvreader = csv.reader(fd)
for row in csvreader:
ml.append(row)
data.append(row)
if has_header:
head = ml.pop(0)
head = data.pop(0)
# check if the first column include an index:
if self._checkIndexColumn(ml):
if self._checkIndexColumn(data):
head.pop(0)
for l in ml:
for l in data:
idx.append(l.pop(0))
return ml, head, idx
return data, head, idx
def _checkIndexColumn(self, ml:list[list]) -> bool:
if all(l[0].isdigit() for l in ml):
num = int(ml[0][0])
return all(num+i==int(l[0]) for i,l in enumerate(ml))
def _checkIndexColumn(self, data:list[list]) -> bool:
if all(l[0].isdigit() for l in data):
num = int(data[0][0])
return all(num+i==int(l[0]) for i,l in enumerate(data))
return False

39
TermTk/TTkWidgets/TTkModelView/tablemodellist.py

@ -26,31 +26,44 @@ from TermTk.TTkCore.constant import TTkK
from TermTk.TTkAbstract.abstracttablemodel import TTkAbstractTableModel
class TTkTableModelList(TTkAbstractTableModel):
__slots__ = ('_list','_listOriginal', '_hheader', '_vheader')
def __init__(self, *, list=[], header=[], indexes=[]):
self._list = self._listOriginal = list if list else [['']]
'''
:class:`TTkTableModelList` extends :class:`¬TermTk.TTkAbstract.abstracttablemodel.TTkAbstractTableModel`,
including a basic model with a 2d list data structure
:param data: the 2D List model for the view to present.
:type data: list[list]
:param header: the header labels, defaults to the column number.
:type header: list[str], optional.
:param indexes: the index labels, defaults to the line number.
:type indexes: list[str], optional.
'''
__slots__ = ('_data','_dataOriginal', '_hheader', '_vheader')
def __init__(self, *, data=[], header=[], indexes=[]):
self._data = self._dataOriginal = data if data else [['']]
self._hheader = header
self._vheader = indexes
super().__init__()
def modelList(self) -> list[list]:
return self._list
return self._data
def setModelList(self, modelList:list[list]) -> None:
if modelList == self._list: return
self._list = modelList
if modelList == self._data: return
self._data = modelList
def rowCount(self) -> int:
return len(self._list)
return len(self._data)
def columnCount(self) -> int:
return len(self._list[0]) if self._list else 0
return len(self._data[0]) if self._data else 0
def data(self, row:int, col:int) -> None:
return self._list[row][col]
return self._data[row][col]
def setData(self, row:int, col:int, data:object) -> None:
self._list[row][col] = data
self._data[row][col] = data
def headerData(self, num:int, orientation:int):
if orientation == TTkK.HORIZONTAL:
@ -63,9 +76,9 @@ class TTkTableModelList(TTkAbstractTableModel):
def sort(self, column:int, order:TTkK.SortOrder) -> None:
if column == -1:
self._list = self._listOriginal
self._data = self._dataOriginal
else:
try:
self._list = sorted(self._listOriginal, key=lambda x:x[column], reverse=order==TTkK.SortOrder.DescendingOrder)
self._data = sorted(self._dataOriginal, key=lambda x:x[column], reverse=order==TTkK.SortOrder.DescendingOrder)
except TypeError as _:
self._list = sorted(self._listOriginal, key=lambda x:str(x[column]), reverse=order==TTkK.SortOrder.DescendingOrder)
self._data = sorted(self._dataOriginal, key=lambda x:str(x[column]), reverse=order==TTkK.SortOrder.DescendingOrder)

6
TermTk/TTkWidgets/TTkModelView/tablewidget.py

@ -67,7 +67,8 @@ class TTkHeaderView():
return self._visible
class TTkTableWidget(TTkAbstractScrollView):
'''TTkTableWidget
'''
A :class:`TTkTableWidget` implements a table view that displays items from a model.
::
@ -85,9 +86,6 @@ class TTkTableWidget(TTkAbstractScrollView):
6 2d08FB17EE273F4 Aimee Downs Steele Group Chavezborough
A :class:`TTkTableWidget` implements a table view that displays items from a model.
The :class:`TTkTableWidget` class is one of the Model/View Classes and is part of TermTk's model/view framework.
:class:`TTkTableWidget` implements the methods to allow it to display data provided by models derived from the :class:`~TermTk.TTkAbstract.abstracttablemodel.TTkAbstractTableModel` class.

2
tests/t.ui/test.ui.032.table.07.py

@ -123,7 +123,7 @@ class CustomColorModifier(ttk.TTkAlternateColor):
class MyTableModel(ttk.TTkTableModelList):
def __init__(self, mylist, size=None):
self.size=size
super().__init__(list=mylist)
super().__init__(data=mylist)
def rowCount(self): return super().rowCount() if not self.size else self.size[0]
def columnCount(self): return super().columnCount() if not self.size else self.size[1]

Loading…
Cancel
Save