細節描述
QAbstractItemModel類定義了M/V模式中能與其他組件(components)交互(interoperate)的數據模型(item model)所必須使用的標准接口(interfaces). 它不能夠被直接實例化, 相反, 你應該繼承(subclass)它, 創建一個新的模型.
QAbstractItemModel是一個M/V類, 也是M/V框架下的一部分. 它可以被用作數據試圖的底層數據模型.
如果你需要一個用在QListView或QTableView等其他數據視圖中的模型, 你應該考慮繼承QAbstractListModel或QAbstractTableModel, 而不是這個類.
底層數據模型作為一個表的層次結構暴露給視圖和委托(The underlying data model is exposed to views and delegates as a hierarchy of tables). 如果你不使用層次結構, 那么這個模型就是一個簡單的由行列組成的簡單表格. 每個數據有一個獨一無二的下標QModelIndex.
每個可以通過模型獲取的數據元素(item data)都有一個關聯的模型下標. index()函數可以獲取這個模型下標. 每個下標可能有一個sibling()下標; 子元素有一個parent()下標.
每一個元素有一系列與之相關聯的數據元素, 並且可以通過在模型的data函數中指定一個角色(role)來獲取這些數據元素. itemData()函數可以獲取同一時間下所有可用角色的數據.
用Qt::ItemDataRole可以指定每個角色的數據. Data for individual roles are set individually with setData(), or they can be set for all roles with setItemData().
通過flags()函數可以查看元素能否被選取, 拖拽或進行其他操作.
If an item has child objects, hasChildren() returns true for the corresponding index.
The model has a rowCount() and a columnCount() for each level of the hierarchy. Rows and columns can be inserted and removed with insertRows(), insertColumns(), removeRows(), and removeColumns().
模型通過發送(emit)信號(singal)來表明改變.
The items available through the model can be searched for particular data using the match() function.
繼承(Subclassing)
繼承QAbstractItemModel后, 你至少要實現index(), parent(), rowCount(), columnCount(), 和data()函數. 所有的只讀(read-only)模型都會使用這些函數, 並且是可編輯模型(editable)的基礎函數.
你也可以重新實現hasChildren()函數,來為那些rowCount()函數實現成本很高的模型提供特定的行為. 這使得模型可以限制視圖請求的數據量, 並且可以用作實現模型數據的惰性填充的方式(and can be used as a way to implement lazy population of model data).
如果要生成可編輯模型, 你必須實現setData()函數, 並且重新實現flags()函數, 並確保返回中包含ItemIsEditable. You can also reimplement headerData() and setHeaderData() to control the way the headers for your model are presented.
The dataChanged() and headerDataChanged() signals must be emitted explicitly when reimplementing the setData() and setHeaderData() functions, respectively.
自定義模型必須創建其他組件可用的模型下標. 調用createIndex()函數, 並傳入適當的row, column, 以及一個標識符(identifier), 標識符可以是指針或整型值. 每個元素的這些值的組合必須是獨一無二的. 自定義模型通常在其他重新實現的函數中使用這些唯一標識符來檢索項目數據並訪問有關該項目的父項和子項的信息.
沒有必要支持Qt::ItemDataRole中定義的所有角色. 根據模型中所包含的數據類型的不同, 可能實現data()函數並返回一個更通用類型的有效信息會更有用. 大多數模型至少為Qt::DisplayRole提供項目數據的文本表示, 更好的模型也應為Qt::ToolTipRole和Qt::WhatsThisRole提供有效信息. 這些角色使得模型可以在標准Qt視圖中使用. 對於那些高度特質化的數據, 僅為用戶定義的角色提供數據才是合理的.
模型的數據如果想要可以調整size, 就要實現insertRows(), removeRows(), insertColumns(), 和removeColumns(). 實現這些函數時, 最重要的是, 在事件發生前后, 通知所有連接的視圖, 數據維度改變了.
- An insertRows() implementation must call beginInsertRows() before inserting new rows into the data structure, and endInsertRows() immediately afterwards.
- An insertColumns() implementation must call beginInsertColumns() before inserting new columns into the data structure, and endInsertColumns() immediately afterwards.
- A removeRows() implementation must call beginRemoveRows() before the rows are removed from the data structure, and endRemoveRows() immediately afterwards.
- A removeColumns() implementation must call beginRemoveColumns() before the columns are removed from the data structure, and endRemoveColumns() immediately afterwards.
這些函數發出的專用信號使連接的組件有機會在任何數據變得不可用之前采取措. 使用這些開始和結束功能對插入和刪除操作進行封裝也使模型能夠正確管理持久性模型索引. 如果要正確處理選擇, 則必須確保調用這些函數. 如果您插入或刪除帶有子項的項目, 則無需為子項調用這些函數. 換句話說, 父項管理其子項.
To create models that populate incrementally, you can reimplement fetchMore() and canFetchMore(). If the reimplementation of fetchMore() adds rows to the model, beginInsertRows() and endInsertRows() must be called.
重要函數
未完待續...