Browse Source

docs: improve table tests documentation (#559)

pull/560/head
Pier CeccoPierangioliEugenio 3 months ago committed by GitHub
parent
commit
d6c3ac971f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 48
      tests/t.ui/test.ui.032.table.01.py
  2. 26
      tests/t.ui/test.ui.032.table.02.py
  3. 17
      tests/t.ui/test.ui.032.table.03.py
  4. 31
      tests/t.ui/test.ui.032.table.04.py
  5. 25
      tests/t.ui/test.ui.032.table.05.py
  6. 33
      tests/t.ui/test.ui.032.table.06.py
  7. 20
      tests/t.ui/test.ui.032.table.07.py
  8. 18
      tests/t.ui/test.ui.032.table.08.py
  9. 18
      tests/t.ui/test.ui.032.table.09.py
  10. 48
      tests/t.ui/test.ui.032.table.10.sqlite.py
  11. 21
      tests/t.ui/test.ui.032.table.11.pyside.align.01.py
  12. 22
      tests/t.ui/test.ui.032.table.11.pyside.insert.01.py
  13. 23
      tests/t.ui/test.ui.032.table.11.pyside.insert.02.py
  14. 32
      tests/t.ui/test.ui.032.table.12.py
  15. 20
      tests/t.ui/test.ui.032.table.13.alignment.01.py
  16. 30
      tests/t.ui/test.ui.032.table.13.alignment.02.overloading.py
  17. 37
      tests/t.ui/test.ui.032.table.13.alignment.03.mixin.py
  18. 31
      tests/t.ui/test.ui.032.table.14.list.01.item.py
  19. 33
      tests/t.ui/test.ui.032.table.14.list.02.custom.py
  20. 34
      tests/t.ui/test.ui.032.table.15.test.clipboard.py

48
tests/t.ui/test.ui.032.table.01.py

@ -25,6 +25,24 @@
# Demo inspired from: # Demo inspired from:
# https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel # https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel
'''
TTkTable Basic Example
======================
This example demonstrates the fundamental usage of TTkTable widget with a custom table model.
Key Features Demonstrated:
- Creating a custom table model by extending TTkAbstractTableModel
- Implementing required methods: rowCount(), columnCount(), data()
- Adding custom header data with headerData()
- Implementing column sorting functionality
- Resizing columns to fit content
- Enabling sorting by clicking column headers
The example displays a table of chemical solvents with their physical properties
(boiling point, melting point, density) and allows sorting by any column.
'''
import os import os
import sys import sys
import argparse import argparse
@ -33,27 +51,40 @@ import operator
sys.path.append(os.path.join(sys.path[0],'../..')) sys.path.append(os.path.join(sys.path[0],'../..'))
import TermTk as ttk import TermTk as ttk
# Custom table model that provides data to the TTkTable widget
class MyTableModel(ttk.TTkAbstractTableModel): class MyTableModel(ttk.TTkAbstractTableModel):
def __init__(self, mylist, header, *args): def __init__(self, mylist, header, *args):
super().__init__(*args) super().__init__(*args)
self.mylist = mylist self.mylist = mylist # Store the data as a list of tuples
self.header = header self.header = header # Store column headers
# Return the number of rows in the table
def rowCount(self): def rowCount(self):
return len(self.mylist) return len(self.mylist)
# Return the number of columns in the table
def columnCount(self): def columnCount(self):
return len(self.mylist[0]) return len(self.mylist[0])
# Return the data at the specified row and column
def data(self, row, col): def data(self, row, col):
return self.mylist[row][col] return self.mylist[row][col]
# Provide header labels for columns and rows
def headerData(self, num, orientation): def headerData(self, num, orientation):
if orientation == ttk.TTkK.HORIZONTAL: if orientation == ttk.TTkK.HORIZONTAL:
return self.header[num] return self.header[num] # Return column header text
return super().headerData(num, orientation) return super().headerData(num, orientation)
# Sort the table data by the specified column
def sort(self, col, order): def sort(self, col, order):
"""sort table by given column number col""" """sort table by given column number col"""
# Sort the list by the specified column
self.mylist = sorted(self.mylist, self.mylist = sorted(self.mylist,
key=operator.itemgetter(col)) key=operator.itemgetter(col))
# Reverse if descending order is requested
if order == ttk.TTkK.DescendingOrder: if order == ttk.TTkK.DescendingOrder:
self.mylist.reverse() self.mylist.reverse()
# Notify the table that the data has changed
self.dataChanged.emit() self.dataChanged.emit()
# the solvent data ... # the solvent data ...
@ -118,6 +149,7 @@ data_list = [
('WATER', 100.0, 0.0, 1.0), ('WATER', 100.0, 0.0, 1.0),
('XYLENES', 139.1, -47.8, 0.86)] ('XYLENES', 139.1, -47.8, 0.86)]
# Parse command line arguments for display options
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('-f', help='Full Screen (default)', action='store_true') parser.add_argument('-f', help='Full Screen (default)', action='store_true')
parser.add_argument('-w', help='Windowed', action='store_true') parser.add_argument('-w', help='Windowed', action='store_true')
@ -127,6 +159,7 @@ args = parser.parse_args()
fullScreen = not args.w fullScreen = not args.w
mouseTrack = args.t mouseTrack = args.t
# Create the main TTk application
root = ttk.TTk(title="pyTermTk Table Demo", mouseTrack=mouseTrack) root = ttk.TTk(title="pyTermTk Table Demo", mouseTrack=mouseTrack)
if fullScreen: if fullScreen:
rootTable = root rootTable = root
@ -134,17 +167,22 @@ if fullScreen:
else: else:
rootTable = ttk.TTkWindow(parent=root,pos = (0,0), size=(150,40), title="Test Table 1", layout=ttk.TTkGridLayout(), border=True) rootTable = ttk.TTkWindow(parent=root,pos = (0,0), size=(150,40), title="Test Table 1", layout=ttk.TTkGridLayout(), border=True)
# Create a vertical splitter to hold the table and log viewer
splitter = ttk.TTkSplitter(parent=rootTable,orientation=ttk.TTkK.VERTICAL) splitter = ttk.TTkSplitter(parent=rootTable,orientation=ttk.TTkK.VERTICAL)
# Create the table model with our data
table_model = MyTableModel(data_list, header) table_model = MyTableModel(data_list, header)
# Create the table widget and attach the model
table = ttk.TTkTable(parent=splitter, tableModel=table_model) table = ttk.TTkTable(parent=splitter, tableModel=table_model)
# set column width to fit contents (set font first!) # Automatically resize columns to fit their contents
table.resizeColumnsToContents() table.resizeColumnsToContents()
# enable sorting
# Enable column sorting by clicking on column headers
table.setSortingEnabled(True) table.setSortingEnabled(True)
# Add a log viewer at the bottom of the splitter
splitter.addWidget(ttk.TTkLogViewer(),size=10,title="LOGS") splitter.addWidget(ttk.TTkLogViewer(),size=10,title="LOGS")
root.mainloop() root.mainloop()

26
tests/t.ui/test.ui.032.table.02.py

@ -25,6 +25,24 @@
# Demo inspired from: # Demo inspired from:
# https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel # https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel
'''
TTkTable Advanced Example with Images and Multi-line Text
=========================================================
This example extends the basic table functionality by demonstrating:
Key Features:
- Displaying ANSI art images within table cells
- Multi-line text in cells
- Long text handling
- Custom vertical header labels with prefixes
- Mixed content types (text, numbers, and images)
- Custom color modifiers for alternating row colors
The table contains chemical solvents data with embedded images and
demonstrates how TTkTable handles complex cell content.
'''
import os import os
import sys import sys
import argparse import argparse
@ -34,10 +52,12 @@ import json
sys.path.append(os.path.join(sys.path[0],'../..')) sys.path.append(os.path.join(sys.path[0],'../..'))
import TermTk as ttk import TermTk as ttk
# Load ANSI art images from JSON file
# These images were created using the Dumb Paint Tool and can be displayed in table cells
imagesFile = os.path.join(os.path.dirname(os.path.abspath(__file__)),'ansi.images.json') imagesFile = os.path.join(os.path.dirname(os.path.abspath(__file__)),'ansi.images.json')
with open(imagesFile) as f: with open(imagesFile) as f:
d = json.load(f) d = json.load(f)
# Image exported by the Dumb Paint Tool # Decompress base64-encoded ANSI art images
pepper = ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['pepper']) pepper = ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['pepper'])
python = ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['python']) python = ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['python'])
fire = ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['fire']) fire = ttk.TTkUtil.base64_deflate_2_obj(d['compressed']['fire'])
@ -55,10 +75,12 @@ class MyTableModel(ttk.TTkAbstractTableModel):
return len(self.mylist[0]) return len(self.mylist[0])
def data(self, row, col): def data(self, row, col):
return self.mylist[row][col] return self.mylist[row][col]
# Provide custom header labels for both columns and rows
def headerData(self, num, orientation): def headerData(self, num, orientation):
if orientation == ttk.TTkK.HORIZONTAL: if orientation == ttk.TTkK.HORIZONTAL:
return self.header[num] return self.header[num] # Column headers
if orientation == ttk.TTkK.VERTICAL: if orientation == ttk.TTkK.VERTICAL:
# Create custom row headers with rotating prefixes
prefix = ['aa','bb','cc','dd','ee','ff','gg','Euge'] prefix = ['aa','bb','cc','dd','ee','ff','gg','Euge']
return f"{prefix[num%len(prefix)]}:{num:03}" return f"{prefix[num%len(prefix)]}:{num:03}"
return super().headerData(num, orientation) return super().headerData(num, orientation)

17
tests/t.ui/test.ui.032.table.03.py

@ -25,6 +25,23 @@
# Demo inspired from: # Demo inspired from:
# https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel # https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel
'''
TTkTable Wide Table Example
============================
This example demonstrates table behavior with many columns (20+ columns).
Key Features:
- Horizontal scrolling for wide tables
- Handling tables that exceed screen width
- Same features as previous examples (images, multi-line text)
- Many columns (20 columns total)
- Demonstrates column navigation and viewport management
Useful for testing horizontal scrolling performance and column
visibility management in wide data sets.
'''
import os import os
import sys import sys
import argparse import argparse

31
tests/t.ui/test.ui.032.table.04.py

@ -25,6 +25,23 @@
# Demo inspired from: # Demo inspired from:
# https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel # https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel
'''
TTkTable Custom Size Example
=============================
This example shows how to create a table model with a custom/fixed size
that may differ from the actual data size.
Key Features:
- Table model with optional size parameter
- Demonstrates rowCount() and columnCount() override with custom dimensions
- Wide table with 21 columns (including 'KK-Last' column)
- Shows how to handle tables where displayed size differs from data size
This is useful when you want to display a subset of data or when
implementing lazy loading / virtual scrolling.
'''
import os import os
import sys import sys
import argparse import argparse
@ -49,15 +66,19 @@ class MyTableModel(ttk.TTkAbstractTableModel):
super().__init__(*args) super().__init__(*args)
self.mylist = mylist self.mylist = mylist
self.header = header self.header = header
self.size = size self.size = size # Optional (rows, cols) tuple to override actual data size
# Return custom row count if size is specified, otherwise use actual data length
def rowCount(self): def rowCount(self):
if self.size: if self.size:
return self.size[0] return self.size[0] # Use custom row count
return len(self.mylist) return len(self.mylist) # Use actual data row count
# Return custom column count if size is specified, otherwise use actual data length
def columnCount(self): def columnCount(self):
if self.size: if self.size:
return self.size[1] return self.size[1] # Use custom column count
return len(self.mylist[0]) return len(self.mylist[0]) # Use actual data column count
def data(self, row, col): def data(self, row, col):
return self.mylist[row][col] return self.mylist[row][col]
def headerData(self, num, orientation): def headerData(self, num, orientation):

25
tests/t.ui/test.ui.032.table.05.py

@ -25,6 +25,25 @@
# Demo inspired from: # Demo inspired from:
# https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel # https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel
'''
TTkTable Large Dataset Example
================================
This example demonstrates table performance with large datasets (5000 rows).
Key Features:
- Handling large datasets (5000+ rows) efficiently
- Custom color modifiers for creating rainbow and pattern effects
- Multiple table models with different dataset sizes
- Cell selection demonstration (setSelection)
- Dynamic style switching with custom colors
- Performance testing with varied content (text, images, numbers)
- Rich content mixing: TTkStrings with colors, ANSI images, multiline text
This is useful for performance testing and understanding how TTkTable
handles large amounts of data and complex rendering scenarios.
'''
import os import os
import sys import sys
import argparse import argparse
@ -53,7 +72,13 @@ with open(imagesFile) as f:
images = [fireMini,pepper,python] images = [fireMini,pepper,python]
# Custom color modifier that creates complex color patterns for table rows
# This class extends TTkAlternateColor to provide custom alternating colors
class CustomColorModifier(ttk.TTkAlternateColor): class CustomColorModifier(ttk.TTkAlternateColor):
# Define a color palette with various effects:
# - Blue shades for grouping
# - Green shades for contrast
# - Rainbow effects for visual interest
colors = ( colors = (
[ ttk.TTkColor.bg("#000066"), ttk.TTkColor.bg("#0000FF") ] * 3 + [ ttk.TTkColor.bg("#000066"), ttk.TTkColor.bg("#0000FF") ] * 3 +
[ ttk.TTkColor.bg("#003300"), ttk.TTkColor.bg("#006600") ] + [ ttk.TTkColor.bg("#003300"), ttk.TTkColor.bg("#006600") ] +

33
tests/t.ui/test.ui.032.table.06.py

@ -25,6 +25,27 @@
# Demo inspired from: # Demo inspired from:
# https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel # https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel
'''
TTkTable CSV and Multiple Models Example
=========================================
This example demonstrates advanced table features including CSV support
and management of multiple table models.
Key Features:
- CSV file loading support (via --csv argument)
- Switching between multiple table models
- Custom table model for CSV data (MyTableModelCSV)
- Complex color modifiers with rainbow effects
- Large datasets with mixed content
- Dynamic model switching
- Cell selection and highlighting
Usage:
python test.ui.032.table.06.py --csv yourfile.csv # Load CSV file
python test.ui.032.table.06.py -f # Full screen mode
'''
import os import os
import sys import sys
import csv import csv
@ -48,14 +69,16 @@ args = parser.parse_args()
fullScreen = not args.w fullScreen = not args.w
mouseTrack = args.t mouseTrack = args.t
# CSV file parsing support (currently commented out)
# This code shows how to load CSV files into the table:
# csvData = [] # csvData = []
# if args.csv: # if args.csv:
# sniffer = csv.Sniffer() # sniffer = csv.Sniffer() # Detect CSV format
# has_header = sniffer.has_header(args.csv.read(2048)) # has_header = sniffer.has_header(args.csv.read(2048)) # Check for headers
# args.csv.seek(0) # args.csv.seek(0) # Reset file pointer
# csvreader = csv.reader(args.csv) # csvreader = csv.reader(args.csv) # Create CSV reader
# for row in csvreader: # for row in csvreader:
# csvData.append(row) # csvData.append(row) # Store each row
imagesFile = os.path.join(os.path.dirname(os.path.abspath(__file__)),'../ansi.images.json') imagesFile = os.path.join(os.path.dirname(os.path.abspath(__file__)),'../ansi.images.json')

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

@ -25,6 +25,26 @@
# Demo inspired from: # Demo inspired from:
# https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel # https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel
'''
TTkTableModelList Example
==========================
This example demonstrates using TTkTableModelList, a ready-made list-based
table model that simplifies table creation.
Key Features:
- Using TTkTableModelList instead of custom TTkAbstractTableModel
- Simplified table creation with list data
- No need to implement rowCount(), columnCount(), data() methods
- Full theming and styling support
- Large dataset handling (5000+ rows)
- Custom color modifiers
- Dynamic style switching
TTkTableModelList is ideal when your data is already in a list format
and you don't need custom data access logic.
'''
import os import os
import sys import sys
import csv import csv

18
tests/t.ui/test.ui.032.table.08.py

@ -25,6 +25,24 @@
# Demo inspired from: # Demo inspired from:
# https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel # https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel
'''
TTkTableModelList Multi-line Cell Example
==========================================
This example focuses on displaying multi-line text content in table cells.
Key Features:
- Multi-line text formatting in cells
- Automatic row height adjustment with resizeRowsToContents()
- TTkTableModelList for simplified data management
- Mixed content (short text, long multi-line text)
- Custom row header labels
- Item flags customization (editable vs read-only cells)
This demonstrates how TTkTable handles cells with varying heights
and properly wraps/displays multi-line content.
'''
import os import os
import sys import sys
import csv import csv

18
tests/t.ui/test.ui.032.table.09.py

@ -25,6 +25,24 @@
# Demo inspired from: # Demo inspired from:
# https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel # https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel
'''
TTkTable Interactive Example with Mouse Tracking
================================================
This example demonstrates interactive table features with mouse tracking enabled.
Key Features:
- Mouse tracking enabled by default (mouseTrack=True)
- Multi-line cell content
- Interactive cell hover effects
- Row and column selection
- Item flags for controlling cell editability
- Custom row heights with resizeRowsToContents()
Mouse tracking allows the table to respond to mouse movements,
enabling hover effects and improved interactivity.
'''
import os import os
import sys import sys
import csv import csv

48
tests/t.ui/test.ui.032.table.10.sqlite.py

@ -22,6 +22,28 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
'''
TTkTableModelSQLite3 Example
=============================
This example demonstrates using TTkTableModelSQLite3 to display data
directly from an SQLite3 database.
Key Features:
- Direct SQLite3 database integration with TTkTableModelSQLite3
- Automatic table loading from database
- Database creation if file doesn't exist
- Column sorting support
- Automatic column resizing
- No need to load all data into memory (efficient for large tables)
Usage:
python test.ui.032.table.10.sqlite.py mydatabase.db # Use existing DB
python test.ui.032.table.10.sqlite.py newfile.db # Create new DB
The database will be created with sample user data if it doesn't exist.
'''
import os import os
import sys import sys
import csv import csv
@ -58,14 +80,15 @@ fullScreen = not args.w
mouseTrack = True mouseTrack = True
path = args.file path = args.file
# Helper function to create a sample SQLite database with test data
def _createDB(fileName): def _createDB(fileName):
# Connect to a database (or create one if it doesn't exist) # Connect to a database (creates the file if it doesn't exist)
conn = sqlite3.connect(fileName) conn = sqlite3.connect(fileName)
# Create a cursor object # Create a cursor object for executing SQL commands
cur = conn.cursor() cur = conn.cursor()
# Create a table # Create a users table with various column types
cur.execute('''CREATE TABLE IF NOT EXISTS users ( cur.execute('''CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
name TEXT, name TEXT,
@ -73,18 +96,21 @@ def _createDB(fileName):
location TEXT, location TEXT,
code INTEGER, code INTEGER,
age INTEGER)''') age INTEGER)''')
# Insert data # Insert sample data using parameterized queries (prevents SQL injection)
sqlDef = "INSERT INTO users (name, surname, location, code, age) VALUES (?, ?, ?, ?, ?)" sqlDef = "INSERT INTO users (name, surname, location, code, age) VALUES (?, ?, ?, ?, ?)"
# Generate 20 rows of random data
for _ in range(20): for _ in range(20):
cur.execute(sqlDef, cur.execute(sqlDef,
(random.choice(words), random.choice(words), (random.choice(words), random.choice(words), # Random name and surname
random.choice(words), random.choice(words), # Random location
random.randint(0x10000,0x100000000), random.randint(18,70))) random.randint(0x10000,0x100000000), random.randint(18,70))) # Random code and age
# Commit changes to the database
conn.commit() conn.commit()
# Close the connection
conn.close() conn.close()
# Create the DB if the file does not exists # Create the database file with sample data if it doesn't already exist
if not os.path.exists(path): if not os.path.exists(path):
_createDB(path) _createDB(path)
@ -102,8 +128,14 @@ if fullScreen:
else: else:
rootTable = ttk.TTkWindow(parent=root,pos = (0,0), size=(150,40), title="Test Table", layout=ttk.TTkGridLayout(), border=True) rootTable = ttk.TTkWindow(parent=root,pos = (0,0), size=(150,40), title="Test Table", layout=ttk.TTkGridLayout(), border=True)
# Create a table model that connects directly to the SQLite database
# This model reads data on-demand, making it efficient for large tables
basicTableModel = ttk.TTkTableModelSQLite3(fileName=path, table='users') basicTableModel = ttk.TTkTableModelSQLite3(fileName=path, table='users')
# Create the table widget with the SQLite model and enable sorting
table = ttk.TTkTable(parent=root, tableModel=basicTableModel, sortingEnabled=True) table = ttk.TTkTable(parent=root, tableModel=basicTableModel, sortingEnabled=True)
# Automatically resize columns to fit their content
table.resizeColumnsToContents() table.resizeColumnsToContents()
root.mainloop() root.mainloop()

21
tests/t.ui/test.ui.032.table.11.pyside.align.01.py

@ -22,6 +22,27 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
'''
PySide6 QTableView Alignment Example (for comparison)
======================================================
This is a PySide6/Qt reference example showing how text alignment works
in QTableView. It's provided for comparison with TTkTable alignment.
Key Concepts:
- QAbstractTableModel for data handling
- Qt.DisplayRole for showing data
- Qt.TextAlignmentRole for alignment
- Combining flags: Qt.AlignLeft | Qt.AlignTop
Alignment Options in Qt:
- Horizontal: AlignLeft, AlignCenter, AlignRight, AlignJustify
- Vertical: AlignTop, AlignVCenter, AlignBottom
Compare this with TTkTable alignment in test.ui.032.table.13.alignment.*.py
to see how pyTermTk implements similar functionality in a terminal UI.
'''
from PySide6.QtWidgets import QApplication, QTableView from PySide6.QtWidgets import QApplication, QTableView
from PySide6.QtCore import Qt, QAbstractTableModel from PySide6.QtCore import Qt, QAbstractTableModel

22
tests/t.ui/test.ui.032.table.11.pyside.insert.01.py

@ -22,6 +22,28 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
'''
PySide6 QTableWidget Column Insertion Example (for comparison)
===============================================================
This is a PySide6/Qt reference example showing how to insert columns
into QTableWidget. It's provided for comparison with TTkTable.
Key Operations:
- QTableWidget: Simpler than QTableView, manages data internally
- setHorizontalHeaderLabels(): Set column titles
- setItem(): Place data in cells
- insertColumn(): Add a new column at specific index
- setHorizontalHeaderItem(): Set header for new column
This demonstrates the widget approach (data stored in widget)
rather than the model/view approach used by TTkTable.
Qt provides both approaches:
- QTableWidget: Simple, data in widget (used here)
- QTableView + Model: More flexible, data separate (like TTkTable)
'''
from PySide6.QtWidgets import QApplication, QTableWidget, QTableWidgetItem from PySide6.QtWidgets import QApplication, QTableWidget, QTableWidgetItem
app = QApplication([]) app = QApplication([])

23
tests/t.ui/test.ui.032.table.11.pyside.insert.02.py

@ -22,6 +22,29 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
'''
PySide6 QTableView with QStandardItemModel Column Insertion (for comparison)
============================================================================
This is a PySide6/Qt reference example showing how to insert columns
using the model/view pattern with QStandardItemModel.
Key Concepts:
- QStandardItemModel: Pre-built model for common use cases
- QTableView: View component that displays the model
- insertColumn(): Add column to model
- setHeaderData(): Set column header text
- Qt.Horizontal: Specify horizontal (column) orientation
Model/View Pattern Benefits:
- Separation of data (model) and presentation (view)
- Multiple views can share one model
- Easier to update data without affecting display
This is the pattern that TTkTable follows, providing similar
flexibility and power in a terminal-based interface.
'''
from PySide6.QtWidgets import QApplication, QTableView from PySide6.QtWidgets import QApplication, QTableView
from PySide6.QtGui import QStandardItemModel, QStandardItem from PySide6.QtGui import QStandardItemModel, QStandardItem
from PySide6.QtCore import Qt from PySide6.QtCore import Qt

32
tests/t.ui/test.ui.032.table.12.py

@ -25,6 +25,25 @@
# Demo inspired from: # Demo inspired from:
# https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel # https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel
'''
TTkTable Cell Edit Flags Example
=================================
This example demonstrates controlling cell editability through ItemFlags.
Key Features:
- Custom flags() method to control cell behavior per column
- ItemIsEnabled: Cell can receive focus
- ItemIsEditable: Cell content can be edited
- ItemIsSelectable: Cell can be selected
- Column 0: Only enabled and selectable (not editable)
- Column 1: Enabled and editable (can modify content)
- Other columns: Use default flags
Useful for creating tables with mixed editable/read-only columns,
like forms where some fields are locked and others are user-editable.
'''
import os import os
import sys import sys
import csv import csv
@ -138,15 +157,20 @@ class MyTableModel(ttk.TTkTableModelList):
return f"{prefix[num%len(prefix)]}:{num:03}" return f"{prefix[num%len(prefix)]}:{num:03}"
return super().headerData(num, orientation) return super().headerData(num, orientation)
# Control cell behavior through flags
# This method determines what the user can do with each cell
def flags(self, row: int, col: int) -> ttk.TTkConstant.ItemFlag: def flags(self, row: int, col: int) -> ttk.TTkConstant.ItemFlag:
if col==0: if col==0:
# Column 0: Read-only, can be selected but not edited
return ( return (
ttk.TTkK.ItemFlag.ItemIsEnabled | ttk.TTkK.ItemFlag.ItemIsEnabled | # Can receive focus
ttk.TTkK.ItemFlag.ItemIsSelectable ) ttk.TTkK.ItemFlag.ItemIsSelectable ) # Can be selected
if col==1: if col==1:
# Column 1: Editable, user can modify content
return ( return (
ttk.TTkK.ItemFlag.ItemIsEnabled | ttk.TTkK.ItemFlag.ItemIsEnabled | # Can receive focus
ttk.TTkK.ItemFlag.ItemIsEditable ) ttk.TTkK.ItemFlag.ItemIsEditable ) # Can be edited
# Other columns use default flags
return super().flags(row, col) return super().flags(row, col)

20
tests/t.ui/test.ui.032.table.13.alignment.01.py

@ -26,6 +26,26 @@
# Demo inspired from: # Demo inspired from:
# https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel # https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel
'''
TTkTable Cell Alignment Example
================================
This example demonstrates text alignment within table cells.
Key Features:
- displayData() method returning (TTkString, Alignment) tuples
- Horizontal alignment: LEFT, CENTER, RIGHT, JUSTIFY
- Vertical alignment: TOP, CENTER, BOTTOM
- Combined alignments (e.g., LEFT|TOP, CENTER|CENTER, RIGHT|BOTTOM)
- Per-cell alignment control
- Multi-line text with different alignments
The displayData() method allows returning both the cell content and
its desired alignment, providing fine-grained control over cell presentation.
Alignment constants can be combined using the | (bitwise OR) operator.
'''
import os import os
import sys import sys
import csv import csv

30
tests/t.ui/test.ui.032.table.13.alignment.02.overloading.py

@ -25,6 +25,21 @@
# Demo inspired from: # Demo inspired from:
# https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel # https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel
'''
TTkTable Alignment Example (Method Overloading)
This example demonstrates how to control text alignment in table cells using method overloading.
Each column displays a different alignment type (LEFT, CENTER, RIGHT, JUSTIFIED) by overriding
the displayData() method to return a tuple of (data, alignment).
Key features:
- Custom alignment per column using modulo arithmetic
- Method overloading of headerData() to label alignment types
- Method overloading of displayData() to return (TTkString, Alignment) tuple
- Multi-line cell content demonstrating alignment effects
- Automatic row/column resizing to fit content
'''
import os import os
import sys import sys
import csv import csv
@ -47,7 +62,9 @@ args = parser.parse_args()
fullScreen = not args.w fullScreen = not args.w
mouseTrack = True mouseTrack = True
# Custom table model that overrides display methods to control alignment
class MyTableModel(ttk.TTkTableModelList): class MyTableModel(ttk.TTkTableModelList):
# Override headerData() to label each column with its alignment type
def headerData(self, num, orientation): def headerData(self, num, orientation):
if orientation == ttk.TTkK.HORIZONTAL: if orientation == ttk.TTkK.HORIZONTAL:
if 0 == num%4: if 0 == num%4:
@ -60,7 +77,10 @@ class MyTableModel(ttk.TTkTableModelList):
return f"{num} Justified" return f"{num} Justified"
return super().headerData(num, orientation) return super().headerData(num, orientation)
# Override displayData() to return (data, alignment) tuple
# This method determines how each cell's content is aligned
def displayData(self:ttk.TTkTableModelList, row:int, col:int) -> Tuple[ttk.TTkString, ttk.TTkK.Alignment]: def displayData(self:ttk.TTkTableModelList, row:int, col:int) -> Tuple[ttk.TTkString, ttk.TTkK.Alignment]:
# Cycle through alignment types based on column number
if 0 == col%4: if 0 == col%4:
return self.ttkStringData(row, col), ttk.TTkK.Alignment.LEFT_ALIGN return self.ttkStringData(row, col), ttk.TTkK.Alignment.LEFT_ALIGN
if 1 == col%4: if 1 == col%4:
@ -71,25 +91,31 @@ class MyTableModel(ttk.TTkTableModelList):
return self.ttkStringData(row, col), ttk.TTkK.Alignment.JUSTIFY return self.ttkStringData(row, col), ttk.TTkK.Alignment.JUSTIFY
return super().displayData(row,col) return super().displayData(row,col)
# Create sample data with multi-line content in first column
data_list1 = [[f"{y:03}\npippo\npeppo-ooo"]+[str(x) for x in range(10) ] for y in range(20)] data_list1 = [[f"{y:03}\npippo\npeppo-ooo"]+[str(x) for x in range(10) ] for y in range(20)]
# Add long multi-line text to specific cells to demonstrate alignment
data_list1[1][1] = "abc def ghi\ndef ghi\nghi\njkl - pippo" data_list1[1][1] = "abc def ghi\ndef ghi\nghi\njkl - pippo"
data_list1[2][2] = "abc def ghi\ndef ghi\nghi\njkl - pippo" data_list1[2][2] = "abc def ghi\ndef ghi\nghi\njkl - pippo"
data_list1[3][3] = "abc def ghi\ndef ghi a b c de fgh s\nghi\njkl - pippo" data_list1[3][3] = "abc def ghi\ndef ghi a b c de fgh s\nghi\njkl - pippo"
data_list1[4][4] = "abc def ghi\ndef ghi\nghi\njkl - pippo" data_list1[4][4] = "abc def ghi\ndef ghi\nghi\njkl - pippo"
data_list1[5][5] = "abc def ghi\ndef ghi\nghi\njkl - pippo" data_list1[5][5] = "abc def ghi\ndef ghi\nghi\njkl - pippo"
# Initialize the main application
root = ttk.TTk(title="pyTermTk Table Demo", root = ttk.TTk(title="pyTermTk Table Demo",
mouseTrack=mouseTrack) mouseTrack=mouseTrack)
# Setup layout - either fullscreen or windowed
if fullScreen: if fullScreen:
rootTable = root rootTable = root
root.setLayout(ttk.TTkGridLayout()) root.setLayout(ttk.TTkGridLayout())
else: else:
rootTable = ttk.TTkWindow(parent=root,pos = (0,0), size=(150,40), title="Test Table 1", layout=ttk.TTkGridLayout(), border=True) rootTable = ttk.TTkWindow(parent=root,pos = (0,0), size=(150,40), title="Test Table 1", layout=ttk.TTkGridLayout(), border=True)
# Create table with custom model and auto-resize to fit content
table_model1 = MyTableModel(data=data_list1) table_model1 = MyTableModel(data=data_list1)
table = ttk.TTkTable(parent=rootTable, tableModel=table_model1) table = ttk.TTkTable(parent=rootTable, tableModel=table_model1)
table.resizeRowsToContents() table.resizeRowsToContents() # Adjust row heights for multi-line content
table.resizeColumnsToContents() table.resizeColumnsToContents() # Adjust column widths for content
root.mainloop() root.mainloop()

37
tests/t.ui/test.ui.032.table.13.alignment.03.mixin.py

@ -25,6 +25,22 @@
# Demo inspired from: # Demo inspired from:
# https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel # https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel
'''
TTkTable Alignment Example (Mixin Pattern)
This example demonstrates using a mixin class to control text alignment in table cells.
The mixin pattern allows reusing alignment logic across multiple table models by inheriting
from both the mixin class and the base table model class.
Key features:
- Mixin class (MyTableMixin) containing reusable alignment logic
- Custom alignment per column using modulo arithmetic
- Multiple inheritance combining mixin with TTkTableModelList
- Preserves parent class functionality using super() calls
- Column-specific edit flags (column 0: selectable only, column 1: editable)
- Multi-line cell content demonstrating alignment effects
'''
import os import os
import sys import sys
import csv import csv
@ -47,7 +63,10 @@ args = parser.parse_args()
fullScreen = not args.w fullScreen = not args.w
mouseTrack = True mouseTrack = True
# Mixin class containing reusable alignment logic
# This can be combined with any table model class via multiple inheritance
class MyTableMixin(): class MyTableMixin():
# Override headerData() to label each column with its alignment type
def headerData(self, num, orientation): def headerData(self, num, orientation):
if orientation == ttk.TTkK.HORIZONTAL: if orientation == ttk.TTkK.HORIZONTAL:
if 0 == num%4: if 0 == num%4:
@ -60,8 +79,11 @@ class MyTableMixin():
return f"{num} Justified" return f"{num} Justified"
return super().headerData(num, orientation) return super().headerData(num, orientation)
# Override displayData() to apply custom alignment
# Note: Uses super() to get data from parent class, then modifies alignment
def displayData(self:ttk.TTkTableModelList, row:int, col:int) -> Tuple[ttk.TTkString, ttk.TTkK.Alignment]: def displayData(self:ttk.TTkTableModelList, row:int, col:int) -> Tuple[ttk.TTkString, ttk.TTkK.Alignment]:
data, legacy_align = super().displayData(row,col) data, legacy_align = super().displayData(row,col)
# Cycle through alignment types based on column number
if 0 == col%4: if 0 == col%4:
return data, ttk.TTkK.Alignment.LEFT_ALIGN return data, ttk.TTkK.Alignment.LEFT_ALIGN
if 1 == col%4: if 1 == col%4:
@ -72,37 +94,48 @@ class MyTableMixin():
return data, ttk.TTkK.Alignment.JUSTIFY return data, ttk.TTkK.Alignment.JUSTIFY
return data, legacy_align return data, legacy_align
# Final table model using multiple inheritance (mixin + base model)
# Order matters: MyTableMixin is checked first for method resolution
class MyTableModel(MyTableMixin, ttk.TTkTableModelList): class MyTableModel(MyTableMixin, ttk.TTkTableModelList):
# Override flags() to control which cells are editable
def flags(self, row: int, col: int) -> ttk.TTkConstant.ItemFlag: def flags(self, row: int, col: int) -> ttk.TTkConstant.ItemFlag:
if col==0: if col==0:
# Column 0: Selectable but not editable
return ( return (
ttk.TTkK.ItemFlag.ItemIsEnabled | ttk.TTkK.ItemFlag.ItemIsEnabled |
ttk.TTkK.ItemFlag.ItemIsSelectable ) ttk.TTkK.ItemFlag.ItemIsSelectable )
if col==1: if col==1:
# Column 1: Fully editable
return ( return (
ttk.TTkK.ItemFlag.ItemIsEnabled | ttk.TTkK.ItemFlag.ItemIsEnabled |
ttk.TTkK.ItemFlag.ItemIsEditable ) ttk.TTkK.ItemFlag.ItemIsEditable )
return super().flags(row, col) return super().flags(row, col)
# Create sample data with multi-line content in first column
data_list1 = [[f"{y:03}\npippo\npeppo-ooo"]+[str(x) for x in range(10) ] for y in range(20)] data_list1 = [[f"{y:03}\npippo\npeppo-ooo"]+[str(x) for x in range(10) ] for y in range(20)]
# Add long multi-line text to specific cells to demonstrate alignment
data_list1[1][1] = "abc def ghi\ndef ghi\nghi\njkl - pippo" data_list1[1][1] = "abc def ghi\ndef ghi\nghi\njkl - pippo"
data_list1[2][2] = "abc def ghi\ndef ghi\nghi\njkl - pippo" data_list1[2][2] = "abc def ghi\ndef ghi\nghi\njkl - pippo"
data_list1[3][3] = "abc def ghi\ndef ghi a b c de fgh s\nghi\njkl - pippo" data_list1[3][3] = "abc def ghi\ndef ghi a b c de fgh s\nghi\njkl - pippo"
data_list1[4][4] = "abc def ghi\ndef ghi\nghi\njkl - pippo" data_list1[4][4] = "abc def ghi\ndef ghi\nghi\njkl - pippo"
data_list1[5][5] = "abc def ghi\ndef ghi\nghi\njkl - pippo" data_list1[5][5] = "abc def ghi\ndef ghi\nghi\njkl - pippo"
# Initialize the main application
root = ttk.TTk(title="pyTermTk Table Demo", root = ttk.TTk(title="pyTermTk Table Demo",
mouseTrack=mouseTrack) mouseTrack=mouseTrack)
# Setup layout - either fullscreen or windowed
if fullScreen: if fullScreen:
rootTable = root rootTable = root
root.setLayout(ttk.TTkGridLayout()) root.setLayout(ttk.TTkGridLayout())
else: else:
rootTable = ttk.TTkWindow(parent=root,pos = (0,0), size=(150,40), title="Test Table 1", layout=ttk.TTkGridLayout(), border=True) rootTable = ttk.TTkWindow(parent=root,pos = (0,0), size=(150,40), title="Test Table 1", layout=ttk.TTkGridLayout(), border=True)
# Create table with custom model using mixin pattern
table_model1 = MyTableModel(data=data_list1) table_model1 = MyTableModel(data=data_list1)
table = ttk.TTkTable(parent=rootTable, tableModel=table_model1) table = ttk.TTkTable(parent=rootTable, tableModel=table_model1)
table.resizeRowsToContents() table.resizeRowsToContents() # Adjust row heights for multi-line content
table.resizeColumnsToContents() table.resizeColumnsToContents() # Adjust column widths for content
root.mainloop() root.mainloop()

31
tests/t.ui/test.ui.032.table.14.list.01.item.py

@ -25,6 +25,24 @@
# Demo inspired from: # Demo inspired from:
# https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel # https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel
'''
TTkTable with TTkCellListType Example
======================================
This example demonstrates using TTkCellListType for dropdown lists in cells.
Key Features:
- TTkCellListType: Creates a dropdown/combo box within a cell
- Mixed cell types: booleans, strings, and list selectors
- value parameter: The currently selected item
- items parameter: List of available options
- Interactive selection: Click cell to see dropdown menu
- Automatic cell editor for list types
TTkCellListType is useful for creating tables where users can select
from predefined options, similar to dropdown menus in spreadsheet applications.
'''
import os import os
import sys import sys
import argparse import argparse
@ -46,18 +64,23 @@ fullScreen = not args.w
mouseTrack = True mouseTrack = True
# Create a list of options for the dropdown cells
data_list = [ data_list = [
'Pippo', 'Pluto', 'Paperino', 'Pippo', 'Pluto', 'Paperino',
'Qui', 'Quo', 'Qua', # L'accento non ci va 'Qui', 'Quo', 'Qua', # L'accento non ci va
'Minnie', 'Topolino' 'Minnie', 'Topolino'
] ]
# Generate table data with mixed types:
# Column 0: Boolean checkboxes
# Column 1-2: Simple strings
# Column 3: TTkCellListType dropdown with random selection from data_list
data = [ data = [
[ [
bool(random.randint(0,1)), bool(random.randint(0,1)), # Random True/False
'Pippo', 'Pippo', # Fixed string
'Pluto', 'Pluto', # Fixed string
ttk.TTkCellListType(value=random.choice(data_list), items=data_list) ttk.TTkCellListType(value=random.choice(data_list), items=data_list) # Dropdown list
] for y in range(20) ] for y in range(20)
] ]

33
tests/t.ui/test.ui.032.table.14.list.02.custom.py

@ -25,6 +25,27 @@
# Demo inspired from: # Demo inspired from:
# https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel # https://www.daniweb.com/programming/software-development/code/447834/applying-pyside-s-qabstracttablemodel
'''
TTkTable with Custom Enum Types Example
========================================
This example demonstrates displaying Python Enum types in table cells.
Key Features:
- Custom Enum classes with auto() values
- Enum display using __str__() method
- Boolean Enum (MyEnumYesNo) with True/False values
- Mixed Enum types in different columns
- Automatic enum value rendering
- Random enum selection for variety
The table automatically displays enum values by calling their __str__() method,
making it easy to show meaningful names instead of raw enum values.
Useful for displaying categorical data, status fields, or any predefined
set of options in a human-readable format.
'''
import os import os
import sys import sys
import argparse import argparse
@ -47,20 +68,26 @@ args = parser.parse_args()
fullScreen = not args.w fullScreen = not args.w
mouseTrack = True mouseTrack = True
# Custom Enum for demonstrating enum display in tables
class MyEnum(Enum): class MyEnum(Enum):
Foo=auto() Foo=auto() # auto() generates sequential values automatically
Bar=auto() Bar=auto()
Baz=auto() Baz=auto()
# Override __str__ to display the enum name instead of the full value
def __str__(self): def __str__(self):
return self.name return self.name
# Boolean-like Enum that maps to True/False values
class MyEnumYesNo(Enum): class MyEnumYesNo(Enum):
Yes=True Yes=True # Maps to boolean True
No=False No=False # Maps to boolean False
# Display as "Yes" or "No" instead of "MyEnumYesNo.Yes"
def __str__(self): def __str__(self):
return self.name return self.name
# Allow the enum to be used in boolean contexts
def __bool__(self): def __bool__(self):
return self.value return self.value

34
tests/t.ui/test.ui.032.table.15.test.clipboard.py

@ -22,6 +22,34 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
'''
TTkTable Clipboard Operations Example
======================================
This example demonstrates table clipboard functionality and complex data types.
Key Features:
- Clipboard operations (copy/paste) with Ctrl+C/Ctrl+Z signals enabled
- Mixed data types in cells:
* Hex numbers (formatted strings)
* TTkString with colors
* Boolean values
* TTkCellListType (dropdown lists)
* Custom Enum types
* datetime.time objects
* datetime.date objects
* datetime.datetime objects
- Random data generation for dates and times
- Signal mask configuration for clipboard shortcuts
Usage:
- Select cells and press Ctrl+C to copy
- Use Ctrl+Z for undo (if enabled in application)
This example shows how TTkTable handles various Python data types
and provides built-in clipboard support.
'''
import os import os
import sys import sys
import argparse import argparse
@ -45,21 +73,21 @@ args = parser.parse_args()
fullScreen = not args.w fullScreen = not args.w
mouseTrack = True mouseTrack = True
# Random date between two dates # Helper function to generate random dates within a range
def random_date(start_date, end_date): def random_date(start_date, end_date):
time_between = end_date - start_date time_between = end_date - start_date
days_between = time_between.days days_between = time_between.days
random_days = random.randrange(days_between) random_days = random.randrange(days_between)
return start_date + datetime.timedelta(days=random_days) return start_date + datetime.timedelta(days=random_days)
# Random time # Helper function to generate random times
def random_time(): def random_time():
hour = random.randint(0, 23) hour = random.randint(0, 23)
minute = random.randint(0, 59) minute = random.randint(0, 59)
second = random.randint(0, 59) second = random.randint(0, 59)
return datetime.time(hour, minute, second) return datetime.time(hour, minute, second)
# Random datetime # Helper function to generate random datetimes within a range
def random_datetime(start_datetime, end_datetime): def random_datetime(start_datetime, end_datetime):
time_between = end_datetime - start_datetime time_between = end_datetime - start_datetime
total_seconds = int(time_between.total_seconds()) total_seconds = int(time_between.total_seconds())

Loading…
Cancel
Save