Proxy model example code: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
(Fixed broken-formatted source code to the version at https://tinyurl.com/ycfgrbek and updated it to compile for Qt 5)
(3 intermediate revisions by one other user not shown)
Line 1: Line 1:
{{Cleanup | reason=Auto-imported from ExpressionEngine.}}
[[Category:snippets]]
[[Category:snippets]]
[[Category:HowTo]]
[[Category:HowTo]]
[[Category:Developing with Qt]]
[[Category:Developing with Qt]]


Related to "this FAQ entry":http://developer.qt.nokia.com/faq/answer/how_can_i_implement_my_own_proxy_model_that_is_more_advanced_than_just_sort.
Related to [http://developer.qt.nokia.com/faq/answer/how_can_i_implement_my_own_proxy_model_that_is_more_advanced_than_just_sort this FAQ entry].


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

Revision as of 15:56, 22 June 2018

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();
}