Proxy model example code: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
[[Category:snippets]]<br />[[Category:HowTo]]<br />[[Category:Developing with Qt]]
[[Category:snippets]]
[[Category:HowTo]]
[[Category:Developing with Qt]]


Related to &quot;this FAQ entry&amp;quot;:http://developer.qt.nokia.com/faq/answer/how_can_i_implement_my_own_proxy_model_that_is_more_advanced_than_just_sort.
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.


<code><br />#include &lt;QtGui&amp;gt;
<code>
#include <QtGui>


QList&amp;lt;QStandardItem *&gt; list;
QList<QStandardItem *> list;


class SortProxy : public QAbstractProxyModel<br />{<br /> Q_OBJECT
class SortProxy : public QAbstractProxyModel
{
Q_OBJECT


public:<br /> SortProxy(QObject *parent = 0) : QAbstractProxyModel(parent), hideThem(false)<br /> {<br /> fixModel();<br /> }
public:
SortProxy(QObject *parent = 0) : QAbstractProxyModel(parent), hideThem(false)
{
fixModel();
}


int rowCount(const QModelIndex &amp;parent) const<br /> {<br /> QModelIndex sourceParent;<br /> if (parent.isValid())<br /> sourceParent = mapToSource(parent);<br /> int count = 0;<br /> QMapIterator&amp;lt;QPersistentModelIndex, QPersistentModelIndex&amp;gt; it(proxySourceParent);<br /> while (it.hasNext()) {<br /> it.next();<br /> if (it.value() == sourceParent)<br /> count++;<br /> }<br /> return count;<br /> }
int rowCount(const QModelIndex &amp;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 &amp;) const<br /> {<br /> return 1;<br /> }
int columnCount(const QModelIndex &amp;) const
{
return 1;
}


QModelIndex index(int row, int column, const QModelIndex &amp;parent = QModelIndex()) const<br /> {<br /> QModelIndex sourceParent;<br /> if (parent.isValid())<br /> sourceParent = mapToSource(parent);<br /> QMapIterator&amp;lt;QPersistentModelIndex, QPersistentModelIndex&amp;gt; it(proxySourceParent);<br /> while (it.hasNext()) {<br /> it.next();<br /> if (it.value()  sourceParent &amp;amp;&amp;amp; it.key().row()  row &amp;&amp;<br /> it.key().column() == column)<br /> return it.key();<br /> }<br /> return QModelIndex();<br /> }
QModelIndex index(int row, int column, const QModelIndex &amp;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 &amp;amp;&amp;amp; it.key().row()  row &amp;&amp;
it.key().column() == column)
return it.key();
}
return QModelIndex();
}


QModelIndex parent(const QModelIndex &amp;child) const<br /> {<br /> QModelIndex mi = proxySourceParent.value(child);<br /> if (mi.isValid())<br /> return mapFromSource(mi);<br /> return QModelIndex();<br /> }
QModelIndex parent(const QModelIndex &amp;child) const
{
QModelIndex mi = proxySourceParent.value(child);
if (mi.isValid())
return mapFromSource(mi);
return QModelIndex();
}


QModelIndex mapToSource(const QModelIndex &amp;proxyIndex) const<br /> {<br /> if (!proxyIndex.isValid())<br /> return QModelIndex();<br /> return mapping.key(proxyIndex);<br /> }
QModelIndex mapToSource(const QModelIndex &amp;proxyIndex) const
{
if (!proxyIndex.isValid())
return QModelIndex();
return mapping.key(proxyIndex);
}


QModelIndex mapFromSource(const QModelIndex &amp;sourceIndex) const<br /> {<br /> if (!sourceIndex.isValid())<br /> return QModelIndex();<br /> return mapping.value(sourceIndex);<br /> }
QModelIndex mapFromSource(const QModelIndex &amp;sourceIndex) const
{
if (!sourceIndex.isValid())
return QModelIndex();
return mapping.value(sourceIndex);
}


public slots:<br /> void hideEverythingButA1AndChildren()<br /> {<br /> hideThem = !hideThem;<br /> // Now we set up the proxy &lt;<s>&gt; source mappings<br /> emit layoutAboutToBeChanged();<br /> fixModel();<br /> emit layoutChanged();<br /> }
public slots:
<br />private:<br /> void fixModel()<br /> {<br /> mapping.clear();<br /> proxySourceParent.clear();<br /> for (int i=0;i&amp;lt;list.size();i+'') {<br /> QStandardItem *si = list.at(i);<br /> if (hideThem) {<br /> if (!si-&gt;text().startsWith(&quot;A&amp;quot;) || !si-&gt;parent())<br /> continue;<br /> QModelIndex proxy = createIndex(si-&gt;row(), si-&gt;column(), si-&gt;index().internalPointer());<br /> mapping.insert(QPersistentModelIndex(si-&gt;index()), proxy);<br /> QModelIndex sourceParent;<br /> if (si-&gt;parent()<s>&gt;parent())<br /> sourceParent = si</s>&gt;parent()<s>&gt;index();<br /> proxySourceParent.insert(proxy, sourceParent);<br /> } else {<br /> QModelIndex proxy = createIndex(si</s>&gt;row(), si-&gt;column(), si-&gt;index().internalPointer());<br /> mapping.insert(QPersistentModelIndex(si-&gt;index()), proxy);<br /> QModelIndex sourceParent;<br /> if (si-&gt;parent())<br /> sourceParent = si-&gt;parent()<s>&gt;index();<br /> proxySourceParent.insert(proxy, sourceParent);<br /> }<br /> }<br /> }<br /> QMap&amp;lt;QPersistentModelIndex, QPersistentModelIndex&amp;gt; mapping;<br /> QMap&amp;lt;QPersistentModelIndex, QPersistentModelIndex&amp;gt; proxySourceParent;<br /> bool hideThem;<br />};
void hideEverythingButA1AndChildren()
<br />SortProxy *proxyModel = 0;
{
<br />class Tree : public QTreeView<br />{<br /> Q_OBJECT
hideThem = !hideThem;
<br />public:<br /> Tree(QWidget *parent = 0) : QTreeView(parent)<br /> {<br /> QStandardItemModel *sourceModel = new QStandardItemModel(this);
// Now we set up the proxy <-> source mappings
<br /> QStandardItem *parentA = sourceModel</s>&gt;invisibleRootItem();<br /> for (int i = 0; i &lt; 2;i) {<br /> itemA = new QStandardItem(QString(&quot;A %0&amp;quot;).arg(i));<br /> parentA-&gt;appendRow(itemA);<br /> parentA = itemA;<br /> list.append(itemA);<br /> }<br /> itemA = new QStandardItem(QString(&quot;A 2&amp;quot;));<br /> parentA-&gt;appendRow(itemA);<br /> list.append(itemA);<br /> itemA3 = new QStandardItem(QString(&quot;A 3&amp;quot;));<br /> list.append(itemA3);<br /> parentA-&gt;appendRow(itemA3);<br /> itemA4 = new QStandardItem(QString(&quot;A 4&amp;quot;));<br /> list.append(itemA4);<br /> parentA-&gt;appendRow(itemA4);<br /> itemNonA = new QStandardItem(QString(&quot;Non A&amp;quot;));<br /> list.append(itemNonA);<br /> parentA-&gt;appendRow(itemNonA);
emit layoutAboutToBeChanged();
<br /> QStandardItem *parentB = sourceModel-&gt;invisibleRootItem();<br /> for (int i = 0; i &lt; 3;i) {<br /> itemB = new QStandardItem(QString(&quot;B %0&amp;quot;).arg(i));<br /> parentB-&gt;appendRow(itemB);<br /> parentB = itemB;<br /> list.append(itemB);<br /> }
fixModel();
<br /> QStandardItem *parentC = sourceModel-&gt;invisibleRootItem();<br /> for (int i = 0; i &lt; 3;i) {<br /> itemC = new QStandardItem(QString(&quot;C %0&amp;quot;).arg(i));<br /> parentC-&gt;appendRow(itemC);<br /> parentC = itemC;<br /> list.append(itemC);
emit layoutChanged();
<br /> }
}
<br /> proxyModel = new SortProxy(this);<br /> proxyModel-&gt;setSourceModel(sourceModel);<br /> setModel(proxyModel);<br /> expandAll();<br /> }<br /> QStandardItem *itemA;<br /> QStandardItem *itemA3;<br /> QStandardItem *itemA4;<br /> QStandardItem *itemNonA;<br /> QStandardItem *itemB;<br /> QStandardItem '''itemC;<br />};


<br />#include &quot;main.moc&amp;quot;
private:
<br />int main(int argc, char'''*argv)<br />{<br /> QApplication app(argc, argv);<br /> QWidget widget;<br /> QPushButton *button = new QPushButton(&quot;Make only A1'' 'A' children visible&amp;quot;, &amp;widget);<br /> Tree *tree = new Tree(&amp;widget);<br /> QVBoxLayout *lay = new QVBoxLayout(&amp;widget);<br /> lay</s>&gt;addWidget(button);<br /> QObject::connect(button, SIGNAL (clicked()), proxyModel, SLOT (hideEverythingButA1AndChildren()));<br /> lay-&gt;addWidget(tree);<br /> widget.show();<br /> return app.exec&amp;amp;#40;&amp;#41;;<br />}<br /></code>
void fixModel()
{
mapping.clear();
proxySourceParent.clear();
for (int i=0;i<list.size();i+'') {
QStandardItem *si = list.at(i);
if (hideThem) {
if (!si->text().startsWith("A") || !si->parent())
continue;
QModelIndex proxy = createIndex(si->row(), si->column(), si->index().internalPointer());
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", &amp;widget);
Tree *tree = new Tree(&amp;widget);
QVBoxLayout *lay = new QVBoxLayout(&amp;widget);
lay->addWidget(button);
QObject::connect(button, SIGNAL (clicked()), proxyModel, SLOT (hideEverythingButA1AndChildren()));
lay->addWidget(tree);
widget.show();
return app.exec();
}
</code>

Revision as of 09:50, 25 February 2015


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.

#include <QtGui>

QList<QStandardItem *> list;

class SortProxy : public QAbstractProxyModel
{
 Q_OBJECT

public:
 SortProxy(QObject *parent = 0) : QAbstractProxyModel(parent), hideThem(false)
 {
 fixModel();
 }

int rowCount(const QModelIndex &amp;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 &amp;) const
 {
 return 1;
 }

QModelIndex index(int row, int column, const QModelIndex &amp;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 &amp;amp;&amp;amp; it.key().row()  row &amp;&amp;
 it.key().column() == column)
 return it.key();
 }
 return QModelIndex();
 }

QModelIndex parent(const QModelIndex &amp;child) const
 {
 QModelIndex mi = proxySourceParent.value(child);
 if (mi.isValid())
 return mapFromSource(mi);
 return QModelIndex();
 }

QModelIndex mapToSource(const QModelIndex &amp;proxyIndex) const
 {
 if (!proxyIndex.isValid())
 return QModelIndex();
 return mapping.key(proxyIndex);
 }

QModelIndex mapFromSource(const QModelIndex &amp;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();
 for (int i=0;i<list.size();i+'') {
 QStandardItem *si = list.at(i);
 if (hideThem) {
 if (!si->text().startsWith("A") || !si->parent())
 continue;
 QModelIndex proxy = createIndex(si->row(), si->column(), si->index().internalPointer());
 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", &amp;widget);
 Tree *tree = new Tree(&amp;widget);
 QVBoxLayout *lay = new QVBoxLayout(&amp;widget);
 lay->addWidget(button);
 QObject::connect(button, SIGNAL (clicked()), proxyModel, SLOT (hideEverythingButA1AndChildren()));
 lay->addWidget(tree);
 widget.show();
 return app.exec();
}