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
AutoSpider (talk | contribs) (Decode HTML entity names) |
(Fixed broken-formatted source code to the version at https://tinyurl.com/ycfgrbek and updated it to compile for Qt 5) |
||
Line 8: | Line 8: | ||
<code> | <code> | ||
#include < | #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 | |||
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 && 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: | private: | ||
void fixModel() | |||
{ | |||
mapping.clear(); | |||
proxySourceParent.clear(); | |||
for (int i=0;i<list.size();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 | ||
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 | ||
QStandardItem *si = list.at(i); | |||
if (si->parent()->parent()) | |||
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 | |||
QMap<QPersistentModelIndex, QPersistentModelIndex> mapping; | |||
//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; | SortProxy *proxyModel = 0; | ||
class Tree : public QTreeView | class Tree : public QTreeView | ||
{ | { | ||
Q_OBJECT | |||
public: | 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" | #include "main.moc" | ||
int main(int argc, char | 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> | </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();
}