Proxy model example code

From Qt Wiki
Revision as of 15:56, 22 June 2018 by 10110111 (talk | contribs) (Fixed broken-formatted source code to the version at https://tinyurl.com/ycfgrbek and updated it to compile for Qt 5)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
This article may require cleanup to meet the Qt Wiki's quality standards. Reason: Auto-imported from ExpressionEngine.
Please improve this article if you can. Remove the {{cleanup}} tag and add this page to Updated pages list after it's clean.

Related to this FAQ entry.

#include <QTreeView>
#include <QPushButton>
#include <QVBoxLayout>
#include <QStandardItem>
#include <QApplication>
#include <QAbstractProxyModel>
 
QList<QStandardItem *> list;
 
class SortProxy : public QAbstractProxyModel
{
    Q_OBJECT
 
public:
    SortProxy(QObject *parent = 0) : QAbstractProxyModel(parent), hideThem(false)
    {
        fixModel();
    }
 
    int rowCount(const QModelIndex &parent) const
    {
        QModelIndex sourceParent;
        if (parent.isValid())
            sourceParent = mapToSource(parent);
        int count = 0;
        QMapIterator<QPersistentModelIndex, QPersistentModelIndex> it(proxySourceParent);
        while (it.hasNext()) {
            it.next();
            if (it.value() == sourceParent)
                count++;
        }
        return count;
    }
 
    int columnCount(const QModelIndex &) const
    {
        return 1;
    }
 
    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const
    {
        QModelIndex sourceParent;
        if (parent.isValid())
            sourceParent = mapToSource(parent);
        QMapIterator<QPersistentModelIndex, QPersistentModelIndex> it(proxySourceParent);
        while (it.hasNext()) {
            it.next();
            if (it.value() == sourceParent && it.key().row() == row &&
                it.key().column() == column)
                return it.key();
        }
        return QModelIndex();
    }
 
    QModelIndex parent(const QModelIndex &child) const
    {
        QModelIndex mi = proxySourceParent.value(child);
        if (mi.isValid())
            return mapFromSource(mi);
        return QModelIndex();
    }
 
    QModelIndex mapToSource(const QModelIndex &proxyIndex) const
    {
        if (!proxyIndex.isValid())
            return QModelIndex();
        return mapping.key(proxyIndex);
    }
 
    QModelIndex mapFromSource(const QModelIndex &sourceIndex) const
    {
        if (!sourceIndex.isValid())
            return QModelIndex();
        return mapping.value(sourceIndex);
    }
 
public slots:
        void hideEverythingButA1AndChildren()
        {
            hideThem = !hideThem;
            // Now we set up the proxy <-> source mappings
            emit layoutAboutToBeChanged();
            fixModel();
            emit layoutChanged();
        }
 
private:
    void fixModel()
    {
        mapping.clear();
        proxySourceParent.clear();
 
        //the following list is already populated
        //in the tree view and we shall browse and
        //customize it here
        for (int i=0;i<list.size();i++)
        {
            //pull out a standard item
            QStandardItem *si = list.at(i);
 
            if (hideThem)
            {
                //if the hide item flag is true
 
                //check if the standard item's text start with 'A'
                //of the item is not parent
                if (!si->text().startsWith("A") || !si->parent())
                    continue;
 
 
                //means that we have encountered item that does not start with 'A'
                //or the item is not the parent
 
                //we pull out the model index by creating the model index with the source items
                //row , column
                QModelIndex proxy = createIndex(si->row(), si->column(), si->index().internalPointer());
 
                //insert the source model's index and the proxy index into the map
                mapping.insert(QPersistentModelIndex(si->index()), proxy);
                QModelIndex sourceParent;
 
                if (si->parent()->parent())
                    sourceParent = si->parent()->index();
                proxySourceParent.insert(proxy, sourceParent);
            }
            else
            {
                QModelIndex proxy = createIndex(si->row(), si->column(), si->index().internalPointer());
                mapping.insert(QPersistentModelIndex(si->index()), proxy);
                QModelIndex sourceParent;
                if (si->parent())
                    sourceParent = si->parent()->index();
                proxySourceParent.insert(proxy, sourceParent);
            }
        }
    }
 
    QMap<QPersistentModelIndex, QPersistentModelIndex> mapping;
    QMap<QPersistentModelIndex, QPersistentModelIndex> proxySourceParent;
    bool hideThem;
};
 
SortProxy *proxyModel = 0;
 
class Tree : public QTreeView
{
    Q_OBJECT
 
public:
    Tree(QWidget *parent = 0) : QTreeView(parent)
    {
        QStandardItemModel *sourceModel = new QStandardItemModel(this);
 
        QStandardItem *parentA = sourceModel->invisibleRootItem();
        for (int i = 0; i < 2; ++i) {
            itemA = new QStandardItem(QString("A %0").arg(i));
            parentA->appendRow(itemA);
            parentA = itemA;
            list.append(itemA);
        }
        itemA = new QStandardItem(QString("A 2"));
        parentA->appendRow(itemA);
        list.append(itemA);
        itemA3 = new QStandardItem(QString("A 3"));
        list.append(itemA3);
        parentA->appendRow(itemA3);
        itemA4 = new QStandardItem(QString("A 4"));
        list.append(itemA4);
        parentA->appendRow(itemA4);
        itemNonA = new QStandardItem(QString("Non A"));
        list.append(itemNonA);
        parentA->appendRow(itemNonA);
 
        QStandardItem *parentB = sourceModel->invisibleRootItem();
        for (int i = 0; i < 3; ++i) {
            itemB = new QStandardItem(QString("B %0").arg(i));
            parentB->appendRow(itemB);
            parentB = itemB;
            list.append(itemB);
        }
 
        QStandardItem *parentC = sourceModel->invisibleRootItem();
        for (int i = 0; i < 3; ++i) {
            itemC = new QStandardItem(QString("C %0").arg(i));
            parentC->appendRow(itemC);
            parentC = itemC;
            list.append(itemC);
 
        }
 
        proxyModel = new SortProxy(this);
        proxyModel->setSourceModel(sourceModel);
        setModel(proxyModel);
        expandAll();
    }
    QStandardItem *itemA;
    QStandardItem *itemA3;
    QStandardItem *itemA4;
    QStandardItem *itemNonA;
    QStandardItem *itemB;
    QStandardItem *itemC;
};
 
 
#include "main.moc"
 
int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    QWidget widget;
    QPushButton *button = new QPushButton("Make only A1 + 'A' children visible", &widget);
    Tree *tree = new Tree(&widget);
    QVBoxLayout *lay = new QVBoxLayout(&widget);
    lay->addWidget(button);
    QObject::connect(button, SIGNAL(clicked()), proxyModel, SLOT(hideEverythingButA1AndChildren()));
    lay->addWidget(tree);
    widget.show();
    return app.exec();
}