Proxy model example code: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
[[Category:snippets]] | [[Category:snippets]] | ||
[[Category:HowTo]] | |||
[[Category:Developing with Qt]] | |||
Related to | 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> | <code> | ||
#include <QtGui> | |||
QList | QList<QStandardItem *> list; | ||
class SortProxy : public QAbstractProxyModel | class SortProxy : public QAbstractProxyModel | ||
{ | |||
Q_OBJECT | |||
public: | public: | ||
SortProxy(QObject *parent = 0) : QAbstractProxyModel(parent), hideThem(false) | |||
{ | |||
fixModel(); | |||
} | |||
int rowCount(const QModelIndex &parent) const | 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 | int columnCount(const QModelIndex &) const | ||
{ | |||
return 1; | |||
} | |||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const | 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 &amp;&amp; it.key().row() row && | |||
it.key().column() == column) | |||
return it.key(); | |||
} | |||
return QModelIndex(); | |||
} | |||
QModelIndex parent(const QModelIndex &child) const | 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 | QModelIndex mapToSource(const QModelIndex &proxyIndex) const | ||
{ | |||
if (!proxyIndex.isValid()) | |||
return QModelIndex(); | |||
return mapping.key(proxyIndex); | |||
} | |||
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const | QModelIndex mapFromSource(const QModelIndex &sourceIndex) const | ||
{ | |||
if (!sourceIndex.isValid()) | |||
return QModelIndex(); | |||
return mapping.value(sourceIndex); | |||
} | |||
public slots: | 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", &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(); | |||
} | |||
</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 &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 &amp;&amp; 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();
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", &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();
}