Bases: QAbstractTableModel
Presents a pandas DataFrame in a Qt QTableView without editing capabilities.
Responsibilities
- Report the number of rows and columns based on the DataFrame shape.
- Provide cell data as strings for display.
- Supply header labels (column names for horizontal, row numbers for vertical).
- Allow resetting the underlying DataFrame when data changes.
Source code in src/models/dataframe_model.py
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 | class DataFrameModel(QAbstractTableModel):
"""
Presents a pandas DataFrame in a Qt QTableView without editing capabilities.
Responsibilities:
- Report the number of rows and columns based on the DataFrame shape.
- Provide cell data as strings for display.
- Supply header labels (column names for horizontal, row numbers for vertical).
- Allow resetting the underlying DataFrame when data changes.
"""
# --------------------------------------------------------------------------
# Constructor
# --------------------------------------------------------------------------
def __init__(self, df: pd.DataFrame | None = None, parent=None) -> None:
"""
Initialize the model with an optional DataFrame.
Steps:
1. Calls the superclass constructor with the given parent.
2. If a DataFrame is provided, uses it; otherwise creates an empty DataFrame.
"""
super().__init__(parent)
# Store a copy of the DataFrame or initialize an empty one
self._df = df.copy() if df is not None else pd.DataFrame()
# --------------------------------------------------------------------------
# Required Qt API methods
# --------------------------------------------------------------------------
def rowCount(self, _=QModelIndex()) -> int:
"""
Return the number of rows in the model.
- Reports the number of rows in the underlying DataFrame.
- QModelIndex parameter is ignored for simple table models.
"""
return len(self._df)
def columnCount(self, _=QModelIndex()) -> int:
"""
Return the number of columns in the model.
- Reports the number of columns in the underlying DataFrame.
- Uses DataFrame's columns attribute to count columns.
- QModelIndex parameter is ignored for simple table models.
"""
return len(self._df.columns)
def data(self, ix: QModelIndex, role: int = Qt.DisplayRole): # type: ignore[attr-defined]
"""
Provide data for a given cell and role.
Steps:
1. Check if the requested role is DisplayRole and the index is valid.
2. If so, retrieve the value at DataFrame.iat[row, column] and convert it to string.
3. Otherwise, return None to indicate no data for other roles.
"""
# Only handle display role and valid index
if role == Qt.DisplayRole and ix.isValid(): # type: ignore[attr-defined]
# Convert the DataFrame value to string for display
value = self._df.iat[ix.row(), ix.column()]
return str(value)
return None
# def headerData(self, sec: int, orient: Qt.Orientation, role: int = Qt.DisplayRole): # type: ignore[attr-defined]
# """
# Provide header labels for horizontal and vertical orientations.
#
# Steps:
# 1. Only handle DisplayRole for headers; return None for other roles.
# 2. If orientation is Horizontal, return the column name at index `sec`.
# 3. If orientation is Vertical, return row number as `sec + 1`.
# """
# if role != Qt.DisplayRole: # type: ignore[attr-defined]
# return None
#
# if orient == Qt.Horizontal: # type: ignore[attr-defined]
# # Return the column name for horizontal headers
# return self._df.columns[sec]
# else:
# # Return 1-based row number for vertical headers
# return sec + 1
# --------------------------------------------------------------------------
# Public API for resetting the DataFrame
# --------------------------------------------------------------------------
def set_frame(self, df: pd.DataFrame) -> None:
"""
Replace the underlying DataFrame with a new one and reset the model.
Steps:
1. Call beginResetModel() to notify views that the model will change completely.
2. Store a copy of the new DataFrame (or an empty DataFrame if None is passed).
3. Call endResetModel() to notify views that reset is finished.
"""
self.beginResetModel()
# Safely copy the DataFrame or use empty if None
self._df = df.copy() if df is not None else pd.DataFrame()
self.endResetModel()
|
__init__(df=None, parent=None)
Initialize the model with an optional DataFrame.
Steps
- Calls the superclass constructor with the given parent.
- If a DataFrame is provided, uses it; otherwise creates an empty DataFrame.
Source code in src/models/dataframe_model.py
28
29
30
31
32
33
34
35
36
37
38 | def __init__(self, df: pd.DataFrame | None = None, parent=None) -> None:
"""
Initialize the model with an optional DataFrame.
Steps:
1. Calls the superclass constructor with the given parent.
2. If a DataFrame is provided, uses it; otherwise creates an empty DataFrame.
"""
super().__init__(parent)
# Store a copy of the DataFrame or initialize an empty one
self._df = df.copy() if df is not None else pd.DataFrame()
|
columnCount(_=QModelIndex())
Return the number of columns in the model.
- Reports the number of columns in the underlying DataFrame.
- Uses DataFrame's columns attribute to count columns.
- QModelIndex parameter is ignored for simple table models.
Source code in src/models/dataframe_model.py
52
53
54
55
56
57
58
59
60 | def columnCount(self, _=QModelIndex()) -> int:
"""
Return the number of columns in the model.
- Reports the number of columns in the underlying DataFrame.
- Uses DataFrame's columns attribute to count columns.
- QModelIndex parameter is ignored for simple table models.
"""
return len(self._df.columns)
|
data(ix, role=Qt.DisplayRole)
Provide data for a given cell and role.
Steps
- Check if the requested role is DisplayRole and the index is valid.
- If so, retrieve the value at DataFrame.iat[row, column] and convert it to string.
- Otherwise, return None to indicate no data for other roles.
Source code in src/models/dataframe_model.py
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 | def data(self, ix: QModelIndex, role: int = Qt.DisplayRole): # type: ignore[attr-defined]
"""
Provide data for a given cell and role.
Steps:
1. Check if the requested role is DisplayRole and the index is valid.
2. If so, retrieve the value at DataFrame.iat[row, column] and convert it to string.
3. Otherwise, return None to indicate no data for other roles.
"""
# Only handle display role and valid index
if role == Qt.DisplayRole and ix.isValid(): # type: ignore[attr-defined]
# Convert the DataFrame value to string for display
value = self._df.iat[ix.row(), ix.column()]
return str(value)
return None
|
rowCount(_=QModelIndex())
Return the number of rows in the model.
- Reports the number of rows in the underlying DataFrame.
- QModelIndex parameter is ignored for simple table models.
Source code in src/models/dataframe_model.py
| def rowCount(self, _=QModelIndex()) -> int:
"""
Return the number of rows in the model.
- Reports the number of rows in the underlying DataFrame.
- QModelIndex parameter is ignored for simple table models.
"""
return len(self._df)
|
set_frame(df)
Replace the underlying DataFrame with a new one and reset the model.
Steps
- Call beginResetModel() to notify views that the model will change completely.
- Store a copy of the new DataFrame (or an empty DataFrame if None is passed).
- Call endResetModel() to notify views that reset is finished.
Source code in src/models/dataframe_model.py
100
101
102
103
104
105
106
107
108
109
110
111
112 | def set_frame(self, df: pd.DataFrame) -> None:
"""
Replace the underlying DataFrame with a new one and reset the model.
Steps:
1. Call beginResetModel() to notify views that the model will change completely.
2. Store a copy of the new DataFrame (or an empty DataFrame if None is passed).
3. Call endResetModel() to notify views that reset is finished.
"""
self.beginResetModel()
# Safely copy the DataFrame or use empty if None
self._df = df.copy() if df is not None else pd.DataFrame()
self.endResetModel()
|