QT:QtreeView和自定义QSortFilterProxyModel

时间:2013-04-04 14:31:05

标签: c++ qt4 qtreeview qsortfilterproxymodel

我有一个自定义的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永远不会被命中。

0 个答案:

没有答案