2

I inherited QAbstractItemModel class for my model. To easily insert new items to the model I wrote next method:

void addItem(MyData *parent, MyData *children) {
    QModelIndex idx = createIndex(parent->row(), 0, parent);
    if (!idx.isValid()) {
        return;
    }

    int childCount = parent->getChildCount();
    beginInsertRows(idx, childCount, childCount);
    parent->addChild(children);
    endInsertRows();

    emit layoutChanged(QList<QPersistentModelIndex>{idx});
}

It works well with QListView, but QML's TreeView does not updates values after it once showed it:

int main(int argc, char ** argv) {
    Q_INIT_RESOURCE(ui);
    QApplication application(argc, argv);

    MyModel model;

    for (int i = 0; i < 10; ++ i) {
        MyData *firstLevelItem = new MyData(i);

        for (int k = 0; k < 3; ++ k) {
            MyData *secondLevelItem = new MyData(i);
            model.addItem(firstLevelItem, secondLevelItem);
        }

        model.addItem(model.getRootItem(), firstLevelItem);
    }

    QQuickView view;
    QQmlContext *context = view.rootContext();
    context->setContextProperty("MyModel", &model);

    view.setSource(QUrl("qrc:///ui/form.qml"));
    view.show();

    QTreeView t;
    t.setModel(&model);
    t.show();

    MyData *data = new MyData(2281488);
    model.addItem(model.getRootItem(), data);
    // t displays changes, view - not

    return application.exec();
}

MyData class:

class MyModel;

class MyData: public QObject {
    Q_OBJECT

public:
    explicit MyData() :
        QObject() {
        _parent = nullptr;
    }

    ~MyData() {
        qDeleteAll(_data);
    }

    // getters / setters

    MyData *getChildItem(int index) const {
        if (index < 0 || index >= _data.size()) {
            return nullptr;
        }

        return _data[index];
    }

    int getChildCount() const {
        return _data.size();
    }

    MyData *parent() const {
        return _parent;
    }

    int row() const {
        if (_parent) {
            return _parent->_data.indexOf(const_cast<MyData *>(this));
        } else {
            return 0;
        }
    }

private:
    void addChild(MyData *data) {
        if (data) {
            if (data->_parent) {
                _parent->removeChild(data);
            }
            data->_parent = this;
            _data << data;
        }
    }

    void removeChild(MyData *data) {
        _data.removeAll(data);
    }

    // some private fields

    MyData *_parent;

    QVector<MyData *> _data;

    friend class MyModel;
};
  • 1
    First of all, you shouldn't be emitting `fooChanged` without an enclosing `fooAboutToBeChanged`. But even then, you shouldn't emit a layout change anyway. You're already informing the clients about the change by emitting the `rowsAboutToBeInserted` and `rowsInserted` signals through `beginInsertRows` and `endInsertRows`. – Kuba hasn't forgotten Monica Apr 27 '16 at 13:48
  • Using only begin(end)InsertRows have no result. Maybe there is a problem with idx object? Should I use row index as parent->row() or 0 or anything else? – Deedee Megadoodoo Apr 27 '16 at 13:53
  • I'm not claiming that the `layoutChanged` emission is the only problem, but it's definitely a problem and you shouldn't be doing it :) – Kuba hasn't forgotten Monica Apr 27 '16 at 13:55
  • I agree with you, layoutChanged() will lead to large delays when working with big data sizes – Deedee Megadoodoo Apr 27 '16 at 13:58
  • just a suggestion: wrap QList{idx} to qRegisterMetaType, also as @KubaOber says emitting layoutChanged is a problem – tty6 Apr 27 '16 at 14:16
  • @tty6 "wrap QList{idx} to qRegisterMetaType" Why? The type is not emitted through signals, so what's the point. – Kuba hasn't forgotten Monica Apr 27 '16 at 14:39

1 Answers1

-1

QML's ListView is not suited to display tree-like structures like a directory tree, for example. It only works with list models typically inherited from QAbstractListModel. If you derive your model from QAbstractItemModel, you must specialise it such that it behaves like a list.

Since Qt 5.5 there is a QML TreeView componenent in the module QtQuick.Controls (v1.4). You may want to try this.

Burkhard
  • 169
  • 1
  • 3