我有一个自定义的Hierarchical模型Implemented,它基本上显示在QtreeView中。 我的要求是过滤多列上的数据。该模型的代码如下:
namespace {
const int ColumnCount = 7;
enum Column {Application=0, StartTime, AccountedTime,Activity,Purpose,OffLine,MachineName};
}
QVariant CSapActvtyTreeModel::data(const QModelIndex &index, int role) const
{
qDebug()<<"CSapActvtyTreeModel::data ... start"<<endl;
if (!m_pObjRootItem || !index.isValid() || index.column() < 0 ||
index.column() >= ColumnCount) {
return QVariant();
}
//This is the data display role
if (COnlineSapActvtyItem *item = itemForIndex(index)) {
if (role == Qt::DisplayRole) {
switch (index.column()) {
//Application, StartTime, AccountedTime,Activity,Purpose
case Application: return item->GetTaskName();
case StartTime: return item->GetStartTimeStr();
case AccountedTime: return item->GetAccountedTimeStr();
case Activity: return item->GetActivityType();
case Purpose: return item->GetActivityPurpose();
case OffLine: return (item->IsOnline() ? "1" : "0");
case MachineName: return item->GetMachineName();
default: return QVariant();
}
}
}
return QVariant();
}
int CSapActvtyTreeModel::rowCount(const QModelIndex &parent) const
{
qDebug() << "CSapActvtyTreeModel::rowCount" << endl;
if (parent.isValid() && parent.column() != 0)
return 0;
COnlineSapActvtyItem *parentItem = itemForIndex(parent);
int irowCount = (parentItem ? parentItem->childCount() : 0);
qDebug()<<"Returning row count: "<<irowCount <<endl;
return irowCount;
}
int CSapActvtyTreeModel::columnCount(const QModelIndex &parent) const
{
qDebug() << "CSapActvtyTreeModel::columnCount" << endl;
int iColCount = (parent.isValid() && parent.column() != 0 ? 0 : ColumnCount);
qDebug()<<"Returning Col count: "<<iColCount <<endl;
return iColCount;
}
QModelIndex CSapActvtyTreeModel::index(int row, int column,
const QModelIndex &parent) const
{
qDebug() << "CSapActvtyTreeModel::index" << endl;
if (!m_pObjRootItem || row < 0 || column < 0 || column >= ColumnCount
|| (parent.isValid() && parent.column() != 0))
return QModelIndex();
COnlineSapActvtyItem *parentItem = itemForIndex(parent);
if(parentItem) {
if (COnlineSapActvtyItem *item = parentItem->childAt(row))
return createIndex(row, column, item);
}
return QModelIndex();
}
COnlineSapActvtyItem* CSapActvtyTreeModel::itemForIndex(const QModelIndex &index) const
{
qDebug() << "CSapActvtyTreeModel::itemForIndex" << endl;
if (index.isValid()) {
if (COnlineSapActvtyItem *item = static_cast<COnlineSapActvtyItem*>(
index.internalPointer())) {
return item;
}
}
return m_pObjRootItem;
}
QStringList CSapActvtyTreeModel::pathForIndex(const QModelIndex &index) const
{
qDebug() << "CSapActvtyTreeModel::pathForIndex" << endl;
QStringList path;
QModelIndex thisIndex = index;
while (thisIndex.isValid()) {
path.prepend(data(thisIndex).toString());
thisIndex = thisIndex.parent();
}
return path;
}
QModelIndex CSapActvtyTreeModel::indexForPath(const QStringList &path) const
{
qDebug() << "CSapActvtyTreeModel::indexForPath" << endl;
return indexForPath(QModelIndex(), path);
}
QModelIndex CSapActvtyTreeModel::indexForPath(const QModelIndex &parent,
const QStringList &path) const
{
qDebug() << "CSapActvtyTreeModel::indexForPath2" << endl;
if (path.isEmpty())
return QModelIndex();
for (int row = 0; row < rowCount(parent); ++row) {
QModelIndex thisIndex = index(row, 0, parent);
if (data(thisIndex).toString() == path.at(0)) {
if (path.count() == 1)
return thisIndex;
thisIndex = indexForPath(thisIndex, path.mid(1));
if (thisIndex.isValid())
return thisIndex;
}
}
return QModelIndex();
}
这些是为我的模型实现的主要重载函数。 当我使用此模型时,treeView显示正确的数据。 但是当我将树视图更改为使用仅覆盖filterAcceptRows的自定义代理模型时,树视图不会显示任何内容。另外,我在filterAcceptRows中添加了一个调试跟踪。 filterAcceptRows未被调用。
我设置treeView和模型的方式是:
m_pFilterProxyModel = new CSapFilterProxyModel(); //Derived from QSortFilterProxyModel
treeView->setModel(m_pFilterProxyModel);
m_pMainTreeModel = new CSapActvtyTreeModel(); //My Main model
PopulateMainModel();
m_pFilterProxyModel->setSourceModel(m_pMainTreeModel);
用于构建树的示例Xml
<TA NM="Qt Creator" OL="1" MN="PRADY-LP">
<TA NM="SapienceTray" OL="1" MN="PRADY-LP">
<TM ST="2013-03-29T04:47:02" TT="2100"/>
<AC AT="Development" AP="Sapience Multi Client"/>
</TA>
</TA>
<TA NM="Ms Visual Studio" OL="1" MN="PRADY-LP">
<TA NM="Test" OL="1" MN="PRADY-LP">
<TM ST="2013-03-29T02:47:02" TT="3000"/>
<AC AT="Development" AP="Sapience Multi Client"/>
</TA>
<TA NM="Number Crunching" OL="1" MN="PRADY-LP">
<TM ST="2013-03-29T01:47:02" TT="2000"/>
<AC AT="Development" AP="Sapience Multi Client"/>
</TA>
</TA>
我发布大量代码的道歉。我对Qt比较陌生。 请提示或暗示可能出现的问题?为什么我的filterAcceptRows没有被调用。
这就是代理模型的实现方式。
#include <QDate>
#include <QSortFilterProxyModel>
class CSapFilterProxyModel : public QSortFilterProxyModel {
Q_OBJECT
public:
CSapFilterProxyModel(QObject* parent = 0);
virtual ~CSapFilterProxyModel();
//All the filtering criteria go in here...
bool FilterOnLine() const { return m_bIsDisplayForOnLine; }
void SetFilterForOnline(bool bOnline);
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
private:
bool MatchMe(int iCol,int sourceRow,
const QModelIndex &sourceParent) const;
bool IsFilterOnline(int iOnLine) const;
private:
//Filter Criteria
bool m_bIsDisplayForOnLine; //Whether we are displaying online data or offline data
};
和.cpp文件是
#include "CSapFilterProxyModel.h"
#include <QStringList>
#include "CSapUtils.h"
#include <QDebug>
CSapFilterProxyModel::CSapFilterProxyModel(QObject *parent):
QSortFilterProxyModel(parent),
m_bIsDisplayForOnLine(true) {
qDebug() << "Constructor called" << endl;
}
CSapFilterProxyModel::~CSapFilterProxyModel() {
qDebug() << "~CSapFilterProxyModel called" << endl;
}
void CSapFilterProxyModel::SetFilterForOnline(bool bOnline) {
qDebug() << "SetFilterForOnline called" << endl;
m_bIsDisplayForOnLine = bOnline;
invalidateFilter();
}
bool CSapFilterProxyModel::IsFilterOnline(int iOnLine) const {
qDebug() << "IsFilterOnline called" << endl;
if(!m_bIsDisplayForOnLine) {
if(iOnLine == 0) {
return true;
} else {
return false;
}
} else {
if(iOnLine == 1) {
return true;
} else {
return false;
}
}
}
bool CSapFilterProxyModel::filterAcceptsRow(int sourceRow,
const QModelIndex &sourceParent) const {
qDebug() << "filterAcceptsRow called" << endl;
bool bIsAccepted = true;
bIsAccepted = bIsAccepted && MatchMe(1,sourceRow,sourceParent);
return bIsAccepted;
}
bool CSapFilterProxyModel::MatchMe(int iCol,int sourceRow,
const QModelIndex &sourceParent) const {
QModelIndex index5 = sourceModel()->index(sourceRow, iCol, sourceParent);
return IsFilterOnline(sourceModel()->data(index5).toString().toInt());
}
请注意,为清晰起见,这是一个精简版。还有其他匹配标准。 filterAcceptsRow永远不会被命中。