123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- #ifndef TABLEVIEWEX_H
- #define TABLEVIEWEX_H
- #include <QWidget>
- #include <QTableView>
- #include <QStandardItemModel>
- #include <QDebug>
- class TableViewEx : public QTableView
- {
- Q_OBJECT
- public:
- explicit TableViewEx(QWidget *parent = nullptr);
- template<typename T> void Load(const QList<T> &dataList, bool selectFirstRow = true, bool appendMode = false);
- template<typename T> void AppendRow(const T &outData, bool setSelected = false);
- template<typename T> void InsertRow(const T &data, int nRow);
- template<typename T> void RefreshOneRow(const T &data);
- template<typename T> bool GetSelected(T &outData);
- template<typename T> void SetSelected(const T &data, bool selectFirstIfNotFound = true, bool scrollto = true);
- template<typename T> int FindData(T &outData, int id, bool forSourceModel = false);
- template<typename T> bool FindData(T &outData, const QModelIndex &index, bool forSourceModel = false);
- template<typename T> bool GetData(QList<T> &outList, bool forSourceModel = false);
-
-
- void ClearModel();
- bool RemoveRow(int row);
- bool RemoveRow(const QModelIndex &index);
- bool IsEmpty(bool forSourceModel = false);
- void SetCurrentRow(int row);
- //自定义横纵滚动条
- void SetVerticalScrollBar(bool bIsNeed);
- void SetHorizontalScrollBar(bool bIsNeed);
- private slots:
- void OnScrollBarDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>());
- void OnModelReset();
- protected:
- QAbstractItemModel *GetModel(bool sourceModel);
- virtual QList<QStandardItem*> Data2RowItems(const QVariant &data, int row) = 0;
- virtual int GetDataID(const QVariant &data) = 0;
- virtual void SetHeaders() = 0;
- virtual void OnLoaded(){}
- protected:
- QStandardItemModel m_model;
- QScrollBar *m_verticalScrollBar{nullptr};
- QScrollBar *m_horizontalScrollBar{nullptr};
- };
- /*----------------------------------------------------------------
- * 因为使用了模板, 模板的实例化在cpp文件中, 其他类要调用模板函数时, 要找到实例化的函数, 所以这里必须写在头文件里
- ----------------------------------------------------------------*/
- template<typename T>
- void TableViewEx::Load(const QList<T> &dataList, bool selectFirstRow, bool appendMode)
- {
- if(!appendMode) m_model.clear();
- for(const T &data: dataList)
- {
- QVariant d_T;
- d_T.setValue(data);
-
- //如果Data2RowItems失败, 这里直接return, 否则下面setdata会越界
- QList<QStandardItem*> rowItems = Data2RowItems(d_T, m_model.rowCount());
- if(rowItems.isEmpty()) return;
-
- m_model.appendRow(rowItems);
-
- QModelIndex index = m_model.index(m_model.rowCount()-1, 0);
- m_model.setData(index, d_T, Qt::UserRole);
- }
- SetHeaders();
-
- //加载完成后选中第一个
- if(selectFirstRow && !dataList.isEmpty()) SetCurrentRow(0);
-
- OnLoaded();
- }
- template<typename T>
- void TableViewEx::AppendRow(const T &data, bool setSelected)
- {
- QVariant d_T;
- d_T.setValue(data);
-
- //如果Data2RowItems失败, 这里直接return, 否则下面setdata会越界
- QList<QStandardItem*> rowItems = Data2RowItems(d_T, m_model.rowCount());
- if(rowItems.isEmpty()) return;
-
- m_model.appendRow(rowItems);
-
- QModelIndex index = m_model.index(m_model.rowCount()-1, 0);
- m_model.setData(index, d_T, Qt::UserRole);
- SetHeaders();
- if(setSelected) SetSelected(data);
- }
- template<typename T>
- void TableViewEx::InsertRow(const T &data, int nRow)
- {
- QVariant d_T;
- d_T.setValue(data);
- //如果Data2RowItems失败, 这里直接return, 否则下面setdata会越界
- QList<QStandardItem*> rowItems = Data2RowItems(d_T, m_model.rowCount());
- if(rowItems.isEmpty()) return;
- m_model.insertRow(nRow, rowItems);
- QModelIndex index = m_model.index(nRow, 0);
- m_model.setData(index, d_T, Qt::UserRole);
- SetHeaders();
- }
- template<typename T>
- void TableViewEx::RefreshOneRow(const T &data)
- {
- QVariant d_data;
- d_data.setValue(data);
- T t;
- int row = FindData(t, GetDataID(d_data), true);
- if(row == -1) return;
-
- //修改表格里的文本
- QList<QStandardItem*> rowItems = Data2RowItems(d_data, row);
- for(QStandardItem *pItem: rowItems)
- {
- m_model.item(row, rowItems.indexOf(pItem))->setText(pItem->text());
- }
- qDeleteAll(rowItems);
-
- //修改存在model第一列的data
- QModelIndex index = m_model.index(row, 0);
- m_model.setData(index, d_data, Qt::UserRole);
- }
- template<typename T>
- bool TableViewEx::GetSelected(T &outData)
- {
- //如果使用了代理model, 则该函数失效, 因为currentIndex().row()返回的是代理model的当前行
- //if((&m_model) != model())
- //{
- // qDebug()<<"使用了代理model, GetSelected失败";
- // return false;
- //}
-
- if(currentIndex().row() == -1) return false;
- QVariant modelData = model()->data(model()->index(currentIndex().row(), 0), Qt::UserRole);
- if(!modelData.isValid()) return false;
- if(!modelData.canConvert<T>()) return false;
- outData = modelData.value<T>();
- return true;
- }
- template<typename T>
- void TableViewEx::SetSelected(const T &data, bool selectFirstIfNotFound, bool scrollto)
- {
- if(m_model.rowCount() == 0) return;
-
- QVariant d_data;
- d_data.setValue(data);
-
- //先取消选中, 再选中回原来那行
- selectionModel()->clear();
-
- //这里直接按正在使用的model来FindData, 不管table是否使用了代理model, 返回的row传给SetCurrentRow都合理
- T t;
- int row = FindData(t, GetDataID(d_data), false);
- if(row == -1)
- {
- if(selectFirstIfNotFound) SetCurrentRow(0);
- }
- else
- {
- SetCurrentRow(row);
- }
- if(scrollto) scrollTo(currentIndex());
- }
- template<typename T>
- int TableViewEx::FindData(T &outData, int id, bool forSourceModel)
- {
- QAbstractItemModel *pModel = GetModel(forSourceModel);
-
- for (int row = 0; row < pModel->rowCount(); ++row)
- {
- QVariant modelData = pModel->data(pModel->index(row, 0), Qt::UserRole);
- if(!modelData.isValid()) continue;
- if(GetDataID(modelData) != id) continue;
- if(!modelData.canConvert<T>()) continue;
- outData = modelData.value<T>();
- return row;
- }
- return -1;
- }
- template<typename T>
- bool TableViewEx::FindData(T &outData, const QModelIndex &index, bool forSourceModel)
- {
- QAbstractItemModel *pModel = GetModel(forSourceModel);
-
- QModelIndex rowIndex = pModel->index(index.row(), 0);
- if(!pModel->data(rowIndex, Qt::UserRole).canConvert<T>()) return false;
- outData = pModel->data(rowIndex, Qt::UserRole).value<T>();
- return true;
- }
- template<typename T>
- bool TableViewEx::GetData(QList<T> &outList, bool forSourceModel)
- {
- QAbstractItemModel *pModel = GetModel(forSourceModel);
- outList.clear();
- for (int row = 0; row < pModel->rowCount(); ++row)
- {
- QVariant modelData = pModel->data(pModel->index(row, 0), Qt::UserRole);
- if(!modelData.isValid()) return false;
- if(!modelData.canConvert<T>()) return false;
- outList.append(modelData.value<T>());
- }
- return true;
- }
- #endif // TABLEVIEWEX_H
|