Smarter way to get a list of children in Tree Model



  • Hi guys, I'm being lazy here. Do you know of any Proxy model that shows only a certain level of a tree as a list?

    What I need is to turn something like

    • Item 1
      • Item 2
      • Item 3
    • Item 4
      • Item 5

    into:
    when level property is 0

    • Item 1
    • Item 4

    when level property is 1

    • Item 2
    • Item 3
    • Item 5

    I achieved it already using 3 proxies concatenated but wanted to know if there is a 1 proxy way already available.

    My current solution:

    #include <QIdentityProxyModel>
    
    class LevelDataProxy : public QIdentityProxyModel
    {
        Q_OBJECT
    
    public:
        explicit LevelDataProxy(QObject *parent = nullptr) : QIdentityProxyModel(parent) {}
        virtual ~LevelDataProxy() = default;
        enum {
            LevelDataRole = 1989
        };
        virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override{
        if (index.isValid() && role == LevelDataRole) {
            Q_ASSERT(index.model() == this);
            int result = 0;
            for (QModelIndex cursor(index); cursor.parent().isValid(); cursor = cursor.parent(), ++result) {}
            return result;
        }
        return QIdentityProxyModel::data(index, role);
    }
    };
    
    

    and then I use it and a QSortFilterProxyModel with a KDescendantsProxyModel in the middle:

        // QAbstractItemModel* originalModel;
        LevelDataProxy* levelInfoProxy = new LevelDataProxy(&printSettingDialog);
        levelInfoProxy->setSourceModel(originalModel);
        KDescendantsProxyModel* flatModel = new KDescendantsProxyModel(&printSettingDialog);
        flatModel->setSourceModel(levelInfoProxy);
        flatModel->setDisplayAncestorData(false);
        QSortFilterProxyModel* levelInfoFilter = new QSortFilterProxyModel(&printSettingDialog);
        levelInfoFilter->setFilterRole(LevelDataProxy::LevelDataRole);
        levelInfoFilter->setFilterFixedString("1");
        levelInfoFilter->setSourceModel(flatModel);
    

  • Moderators

    @VRonin
    How about re-implementing filterAcceptsRow in QSortFilterProxyModel and return true or false depending upon source_parent ? For eg. Item 1 and Item 4 has invisible root as their parent but the their children don't.
    Just a non educated guess. Haven't tried myself.


  • Qt Champions 2016

    Another speculative suggestion:
    I don't really like the idea of deriving from the identity proxy and then overriding data(), somehow feels wrong. You want to change the structure, not the data. What I'd try if I were you, is to subclass QAbstractProxyModel and do that depth-search like thingy only once, to obtain a QModelIndex for the "parent". After that in the index* methods (especially relevant seems hasIndex()) I'd return invalid model indexes for items that aren't parented to the parent I've stored in the beginning.

    I hope that helps.
    Kind regards.



  • @p3c0 Most views would hide all children if the parent is hidden so you won't be able to achieve a list of children

    @kshegunov the overridden data is to store somewhere the level in the original tree before it gets flattened by KDescendantsProxyModel. I know it's ugly and dirty that's why I asked the question. The second part seems pretty much the way to go but since this I need this just to show a combobox I didn't feel like going through building a QAbstractProxyModel from scratch


  • Qt Champions 2016

    @VRonin said in Smarter way to get a list of children in Tree Model:

    the overridden data is to store somewhere the level in the original tree before it gets flattened by KDescendantsProxyModel.

    I don't believe you need that. Pushing a tree model to a list/table view should give you list/table with the root-level items (speculation again!). In my mind it should be just enough to "move" the root of the model before giving it to the view.

    I didn't feel like going through building a QAbstractProxyModel from scratch

    Well, yes, I can see why, but if you think about it, most of your methods should turn out trivial (more or less) - similarly to the identity proxy model.

    Kind regards.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.