I implemented Google's suggestion, but it has no effect. Here's the interesting part of the code:
QAbstractTableModel Subclass
class ColDef:
'''
Store column definitions for a model
Still a work-in-progress
'''
def __init__(self, header:str, attr:str, fmt:str, align:Qt.AlignmentFlag):
self.header = header
self.attr = attr
self.fmt = fmt
self.align = align
def format(self, row) -> str:
if self.attr == '': return ''
val = getattr(row, self.attr)
if self.fmt == 'time':
if isinstance(val, dt.datetime):
return val.strftime("%H:%M")
else: # For now...
return str(val)
return None
columnDefs = [
# Header Field in rowset Format Alignment
# ------------------ ------------------------------ ------- ---------------
ColDef('Scheduled\nStart', 'start_ts', 'time', Qt.AlignCenter),
ColDef('Scheduled\nEnd', 'end_ts', 'time', Qt.AlignCenter),
ColDef('Leader', '', '', Qt.AlignLeft),
ColDef('Actual\nStart', '', '', Qt.AlignCenter),
ColDef('Actual\nEnd', '', '', Qt.AlignCenter),
ColDef('Activity', '', '', Qt.AlignCenter),
ColDef('Description', 'title', '', Qt.AlignLeft),
ColDef('Limit', 'registrations_limit', 'int', Qt.AlignCenter),
ColDef('Reg', 'confirmed_registrations_count', 'int', Qt.AlignCenter),
ColDef('Wait', 'waitlist_registration_count', 'int', Qt.AlignCenter),
]
class SAEventsModel(QAbstractTableModel):
def __init__(self, parent=None, * , dbEngine):
super().__init__()
self.dbEngine = dbEngine
self.rowset = []
self.fontMetrics = None
def setFontMetrics(self, font:QFont):
self.fontMetrics = QFontMetrics(font)
def refresh(self, d:dt.date):
self.beginResetModel()
with Session(self.dbEngine) as dbSession:
stmt = select(DVEventSession)\
.where(DVEventSession.event_date==d)\
.order_by(DVEventSession.start_ts)
self.rowset = dbSession.scalars(stmt).all()
self.endResetModel()
def headerData(self, section:int, orientation:Qt.Orientation, role:Qt.ItemDataRole):
if orientation == Qt.Orientation.Horizontal \
and 0 <= section < len(columnDefs) \
and role == Qt.DisplayRole:
return columnDefs[section].header
return None
def rowCount(self, _) -> int:
return len(self.rowset)
def columnCount(self, _) -> int:
return len(columnDefs)
def data(self, index:QModelIndex, role:Qt.ItemDataRole):
if index.isValid():
row = index.row()
col = index.column()
cd = columnDefs[col]
if role in (Qt.ItemDataRole.DisplayRole, Qt.ItemDataRole.EditRole):
# Table is read-only, return same data for Display and Edit
return cd.format(self.rowset[row])
elif role == Qt.ItemDataRole.SizeHintRole:
# Recalculate the text size
text = cd.format(self.rowset[row])
w = self.fontMetrics.horizontalAdvance(text)
h = self.fontMetrics.height()
return QSize(w+20, h+10)
elif role == Qt.ItemDataRole.TextAlignmentRole:
# Return the desired alignment
return cd.align
return None
Main Window snippet
self.ui is loaded from a QtCreator-generated .ui file. self.ui.guildEvents' is a QTableView`
td = dt.date.today()
self.ui.curDate.setText(f"{td:%B} {td.day} {td:%Y}")
self.model = SAEventsModel(dbEngine=dbEngine)
self.model.refresh(td)
self.model.setFontMetrics(self.ui.guildEvents.font())
self.ui.guildEvents.setModel(self.model)
self.ui.guildEvents.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)
self.ui.guildEvents.setSelectionBehavior(qv.SelectionBehavior.SelectRows)
Main Window Display
The middle row is selected.
[image: f2a96f52-114c-4da5-9f06-ac9df814d4f0.PNG]