Re-root un TreeModel sur une de ses branches

a marqué ce sujet comme résolu.

Salut,

J’essaie de faire un proxymodel Qt qui prend un model sous forme d’arbre et en expose qu’une de ses branches

O
|-A
| |-AA
|   |-X
|
|-B
  |-BB
    |-Y

deviens

O
|-AA
  |-X

si je construit mon Proxy sur le nom "AA"

Mais je ne m’en sort pas avec le système de model Qt, je dois passer à côté de quelque chose, avoir compris la doc de travers.

J’ai implémenté un QAbstractProxyModel pour arriver à mes fins. Malheureusement, lorsque je l’associe à une TreeView, un Q_ASSERT du setModel se déclanche : "The parent of a top level index should be invalid". Pourtant je crois bien avoir associé un QModelIndex invalide en tant que parent de ma nouvelle racine (en le mappant).

Voici le code que j’ai écrit :

branchproxymodel.h

#ifndef BRANCHPROXYMODEL_H
#define BRANCHPROXYMODEL_H

#include <QAbstractProxyModel>

class BranchProxyModel : public QAbstractProxyModel
{
public:
    BranchProxyModel(const QString & branchname, QObject* parent = nullptr);
    ~BranchProxyModel() override;

    void setSourceModel(QAbstractItemModel *sourceModel) override;

    QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override;
    QModelIndex mapToSource(const QModelIndex &proxyIndex) const override;

    int columnCount(const QModelIndex & parent) const override;
    int rowCount(const QModelIndex & parent) const override;

    QModelIndex index(int row, int column, const QModelIndex & parent) const override;
    QModelIndex parent(const QModelIndex & index) const override;

public slots:
    void sourceDataChanged(QModelIndex topLeft, QModelIndex bottomRight);

private:
    void extractBranch(const QModelIndex & branchIndex, const QModelIndex &parent= QModelIndex());
    QModelIndex findIndexOfBranch(QAbstractItemModel* model, const QModelIndex & parent = QModelIndex()) const;

    QString m_branchName;
    QModelIndex m_branchRoot;
    QMap<QModelIndex, QModelIndex> m_indexMap;
    QMap<QModelIndex, QModelIndex> m_parentMap;
};

#endif // BRANCHPROXYMODEL_H

branchproxymodel.cpp

#include "gui/typeexplorer/branchproxymodel.h"

#include <QDebug>

BranchProxyModel::BranchProxyModel(const QString &branchname, QObject *parent):
    QAbstractProxyModel(parent),
    m_branchName(branchname),
    m_branchRoot(),
    m_indexMap(),
    m_parentMap()
{
}

BranchProxyModel::~BranchProxyModel()
{
}

void BranchProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
    QAbstractProxyModel::setSourceModel(sourceModel);

    m_branchRoot = findIndexOfBranch(sourceModel);
    extractBranch(m_branchRoot);
    connect(sourceModel, &QAbstractItemModel::dataChanged, this, &BranchProxyModel::sourceDataChanged);
}

QModelIndex BranchProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
{
    if(m_indexMap.contains(sourceIndex))
        return m_indexMap[sourceIndex];
    else
        return QModelIndex();
}

QModelIndex BranchProxyModel::mapToSource(const QModelIndex &proxyIndex) const
{
    if(!proxyIndex.isValid())
        return QModelIndex();
    else if(!proxyIndex.parent().isValid())
        return m_branchRoot;
    else
    {
        QModelIndex sourceParent = mapToSource(proxyIndex.parent());
        return sourceModel()->index(proxyIndex.row(), proxyIndex.column(), sourceParent);
    }
}

int BranchProxyModel::columnCount(const QModelIndex &parent) const
{
    return sourceModel()->columnCount(mapToSource(parent));
}

int BranchProxyModel::rowCount(const QModelIndex &parent) const
{
    if(!parent.isValid())
        return 1;
    else
        return sourceModel()->rowCount(mapToSource(parent));
}

QModelIndex BranchProxyModel::index(int row, int column, const QModelIndex &parent) const
{
    if(!parent.isValid())
        return m_indexMap[m_branchRoot];
    else
        return m_indexMap[mapToSource(parent)].child(row, column);
}

QModelIndex BranchProxyModel::parent(const QModelIndex &index) const
{
    return m_parentMap[index];
}

void BranchProxyModel::sourceDataChanged(QModelIndex topLeft, QModelIndex bottomRight)
{
    emit dataChanged(mapFromSource(topLeft), mapFromSource(bottomRight));
}

void BranchProxyModel::extractBranch(const QModelIndex & branchIndex, const QModelIndex &parent)
{
    if(!parent.isValid())
    {
        m_indexMap.clear();
        m_parentMap.clear();
    }
    if(branchIndex.column() == 0)
    {
        QModelIndex proxyIndex;
        if(branchIndex == m_branchRoot)
            proxyIndex = createIndex(0, branchIndex.column());
        else
            proxyIndex = createIndex(branchIndex.row(), branchIndex.column());
        m_indexMap.insert(branchIndex, proxyIndex);
        m_parentMap.insert(proxyIndex, parent);
        for(int i = 0; i < sourceModel()->rowCount(branchIndex); ++i)
        {
            extractBranch(branchIndex.child(i, 0), proxyIndex);
        }
    }
}

QModelIndex BranchProxyModel::findIndexOfBranch(QAbstractItemModel *model, const QModelIndex &parent) const
{
    for(int i = 0; i < model->rowCount(parent); ++i)
    {
        QModelIndex index = model->index(i, 0, parent);
        if(model->data(index) == m_branchName)
        {
            return index;
        }
    }
    QModelIndex resultOfChild;
    for(int i = 0; i < model->rowCount(parent); ++i)
    {
        QModelIndex index = model->index(i, 0, parent);
        resultOfChild = findIndexOfBranch(model, index);
        if(resultOfChild.isValid())
            return resultOfChild;
    }
    return QModelIndex();
}
+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte