QTreeview Custom model and QSortFilterProxyModel
-
I have a custom Hierarchical model Implemented which is basically displayed in a QtreeView. My requirement is to filter data on multiple columns. The code of the model is as follows:
model:@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();
}@These are the major overloaded functions implemented for my model. When I use this model, the treeView displays data correct. But When I changed the treeview to use a custom proxy model which just overrides filterAcceptRows the tree view does not display anything. Also, I added a debug trace in the filterAcceptRows. The filterAcceptRows is not getting called.
The way I set up the treeView and models is:
@m_pFilterProxyModel = new CSapFilterProxyModel(); //Derived from QSortFilterProxyModel
treeView->setModel(m_pFilterProxyModel);m_pMainTreeModel = new CSapActvtyTreeModel(); //My Main model
PopulateMainModel();
m_pFilterProxyModel->setSourceModel(m_pMainTreeModel);
@Sample Xml using which I build the tree
@
<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>
@This is how the proxymodel is implemented.
FilterAcceptsRow is not getting called. What could be the problem???
-
Andre, yes my function overload is correct.
My trimmed down derivation of QSortFilterProxyModel is as follows:
////.h
@
#include <QDate>
#include <QSortFilterProxyModel>class CSapFilterProxyModel : public QSortFilterProxyModel {
Q_OBJECTpublic:
CSapFilterProxyModel(QObject* parent = 0);
virtual ~CSapFilterProxyModel();//All the filtering criteria go in here...
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;private:
//Data members and helper functions here
};
@and the .cpp file is :
@
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 {
//return true or false based on matching criteria
}
@Also the way I load the XML into my data structure (for reference just in case),
where pObjTask contains the root item pointer.
@
void CSapActvtyTreeModel::readTasks(QXmlStreamReader *reader, COnlineSapActvtyItem *pObjTask)
{
qDebug() << "CSapActvtyTreeModel::readTasks" << endl;
while ((reader && !reader->atEnd())) {
reader->readNext();
if (reader->isStartElement()) {
if (reader->name() == TaskTag) { //TA
QString strName = reader->attributes()
.value(NameAttribute).toString();bool bIsOnLine = reader->attributes() .value(OnLineAttribute) == "1"; QString strMachineName = reader->attributes() .value(MachinNameAttribute).toString(); pObjTask = new COnlineSapActvtyItem(NULL,pObjTask); pObjTask->SetTaskName(strName); pObjTask->SetOnlineFlag(bIsOnLine); pObjTask->SetMachineName(strMachineName); } else if(reader->name() == TimeTag) { //TM Q_ASSERT(pObjTask); QDateTime objStartTime = QDateTime::fromString( reader->attributes().value(StartTimeAttribute) .toString(), Qt::ISODate); int iTotalTime = reader->attributes().value(TotalTimeAttribute) .toString().toInt(); pObjTask->SetStartTime(objStartTime); pObjTask->SetAccountedTime(iTotalTime); } else if (reader->name() == ActvtyTag) { //AC Q_ASSERT(pObjTask); QString strActvtyType = reader->attributes().value(ActvtyTypeAttribute) .toString(); QString strActvtyPurpose = reader->attributes().value(ActvtyPurposeAttribute) .toString(); pObjTask->SetActvtyType(strActvtyType); pObjTask->SetActvtyPurpose(strActvtyPurpose); } } else if (reader->isEndElement()) { if (reader->name() == TaskTag) { //TA end Q_ASSERT(pObjTask); pObjTask = pObjTask->parent(); Q_ASSERT(pObjTask); } } }
}
@Please let me know. Thanks