Qt wiki will be updated on October 12th 2023 starting at 11:30 AM (EEST) and the maintenance will last around 2-3 hours. During the maintenance the site will be unavailable.
Proxy model example code: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
m (Fix code tags) |
||
(6 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
{{Cleanup | reason=Auto-imported from ExpressionEngine.}} | |||
[[Category:snippets]] | |||
[[Category:HowTo]] | |||
[[Category:Developing with Qt]] | |||
* | 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]. | ||
* | |||
* | <pre> | ||
#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(); | |||
} | |||
</pre> |
Latest revision as of 02:08, 12 August 2022
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(); }