Разделить QAbstarctListModel на подмодели

У меня есть список пользовательских объектов, которые мне нужно разделить на несколько страниц SwipeView.

Прямо сейчас я реализую QAbstractListModel для предоставления данных моему представлению QML через пользовательские роли. Но когда у меня больше заданного количества объектов, мне нужно разделить мою модель на несколько фрагментов, которые будут отображаться на разных страницах SwipeView.

Если моя модель имеет 20 объектов, мой SwipeView будет иметь 2 страницы с 12 элементами на первой и 8 оставшимися на второй странице, например, но количество элементов, конечно, является динамическим.

Я знаю, что могу использовать QSortProxyFilter или DelegateModel для фильтрации моей модели по критериям, но я не знаю, как их использовать для создания групп, которые можно использовать в качестве подмоделей для содержимого страниц SwipeView. Поскольку, конечно, я не могу просто изменить фильтр при изменении страницы, потому что это не сделает элементы видимыми при переходе с одной страницы на другую.

Спасибо за любой намек или идею о том, как этого добиться.


person Bertrand Thelen    schedule 03.04.2020    source источник
comment
Не кажется ли вам, что разные наборы данных должны предоставляться разными моделями? Какой смысл использовать сингл QAbstractListModel ?   -  person folibis    schedule 03.04.2020
comment
Ну, это просто большой список объектов, которые должны отображаться в виде кнопок, поэтому имеет смысл иметь единую модель. и чтобы по-настоящему отделить модель от представления, я даже не должен знать, сколько объектов отображается на странице. Модель предоставляет все данные, и это роль представления для их отображения по мере необходимости (здесь 12 на страницу с любым количеством страниц по мере необходимости).   -  person Bertrand Thelen    schedule 06.04.2020


Ответы (1)


Почему бы вам не включить модель в другую модель? Вернуть модель в QML можно через QVariant::fromValue. Смотрите мой пример:

models.h

class ChildItem{
public:
    ChildItem() {}
};

class ChildModel: public QAbstractListModel{
    Q_OBJECT
public:
    explicit ChildModel(QObject *parent = nullptr);
    void addItem(const ChildItem &item);
    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
signals:
    void itemAdded();
protected:
    QHash<int,QByteArray> roleNames() const;
private:
    QVector<ChildItem> m_items;
};

class ModelItem{
public:
    ModelItem() {}
    ChildModel *childModel() const;
private:
    ChildModel *m_childModel;
};

class MainModel: public QAbstractListModel{
    Q_OBJECT
public:
    explicit MainModel(QObject *parent = nullptr);
    void addItem(const ModelItem &item);
    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
signals:
    void itemAdded();
protected:
    QHash<int,QByteArray> roleNames() const;
private:
    QVector<ModelItem> m_items;
};

models.cpp

ChildModel *ModelItem::childModel() const{
    return m_childModel;
}

QVariant MainModel::data(const QModelIndex & index, int role) const {
    if (index.row() < 0 || index.row() >= (int)m_items.size())
        return QVariant();
    const MainModel &item = m_items[index.row()];
    switch (role) {
    case MainModelRoles::ChildModel:{
        return QVariant::fromValue(item.childModel());
    }
    default: {
        break;
    }
    }
    return QVariant();
}

QHash<int, QByteArray> MainModel::roleNames() const {
    QHash<int, QByteArray> roles;
    roles[MainModelRoles::ChildModel] = "child_model";
    return roles;
}

Изнутри QML вы можете представить имя роли модели как новую модель для другого элемента. Например:

  1. StackLayout, который является вашим основным элементом, включает Repeater.
  2. Модель Repeater является экземпляром класса MainModel.
  3. Repeater делегат включает ListView
  4. ListView берет ChildModel за образец для себя (ссылка child_model)

Таким образом, вы можете содержать любое количество различных моделей внутри основной модели и предоставлять их QML как свойство модели. Это то, что вы ищете?

person user3417815    schedule 06.04.2020