Декларативный способ расширения / объединения нескольких ListModel - PullRequest
1 голос
/ 26 марта 2019

Я хочу построить несколько ListModel, которые будут начинаться с общих элементов.Я хочу заполнить остальные элементы из другого ListModel.

Пример: ListModel (1):

COMMON A
COMMON B
COMMON C
A1
B1
C1

ListModel (2):

COMMON A
COMMON B
COMMON C
A2
B2
C2

Isесть способ декларативно «объединить» или расширить два ListModel?

Пока я делаю это динамически:

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    width: 480
    height: 320
    visible: true

    ListModel {
        id: commonModel
        ListElement { value: "COMMON A" }
        ListElement { value: "COMMON B" }
        ListElement { value: "COMMON C" }
    }

    ListModel {
        id: model1
        ListElement { value: "A1" }
        ListElement { value: "B1" }
        ListElement { value: "C1" }
    }

    ListModel {
        id: model2
        ListElement { value: "A2" }
        ListElement { value: "B2" }
        ListElement { value: "C2" }
    }

    ListView {
        anchors.fill: parent
        model: commonModel // here I would like to directly specify the "concatenated" model

        delegate: Text { text: model.value}

        // dynamic part that I want to avoid
        readonly property var additionalModel: model2
        Component.onCompleted: {
            for (var i = 0; i < additionalModel.count; ++i) {
                var elt = additionalModel.get(i)
                model.append(elt)
            }
        }
    }
}

Редактировать: Другими словами, я хотел бысделать что-то простое, как это:

// MyModel.qml
ListModel {
    ListElement { value: "COMMON A" }
    ListElement { value: "COMMON B" }
    ListElement { value: "COMMON C" }
}

Возможность расширить его по мере необходимости в другом компоненте:

ListView {
    model: MyModel {
        // keep original elements from MyModel and add custom "component-related" elements
        ListElement { value: "OTHER A" }
        ListElement { value: "OTHER B" }
        ListElement { value: "OTHER C" }
    }
}

Но это не представляется возможным, так как я получаю следующую ошибку:

Невозможно назначить несуществующее свойство по умолчанию

1 Ответ

2 голосов
/ 26 марта 2019

Начнем с исправления ошибки. Отсюда:

model: MyModel {
    ListElement { role_value: "OTHER A" }
    ListElement { role_value: "OTHER B" }
    ListElement { role_value: "OTHER C" }
}

Чтобы получить такое поведение, вам нужно установить одно из свойств MyModel в default свойство . Тривиально, что-то вроде

//  MyModel.qml
ListModel {
    default property list<ListElement> otherModels

    ListElement { role_value: "COMMON A" }
    ListElement { role_value: "COMMON B" }
    ListElement { role_value: "COMMON C" }
}

//  Main.qml
import QtQuick 2.0
import QtQuick.Window 2.2

Window {
    ListView {
        model: MyModel {
            // these should be auto-assigned to the default property      
            ListElement { role_value: "OTHER A" }
            ListElement { role_value: "OTHER B" }
            ListElement { role_value: "OTHER C" }
        }
    }
}

Обычно с другими типами это будет работать нормально. Но ListElement это особый случай. Если вы попытаетесь выполнить вышеизложенное, вы, вероятно, получите ошибку:

Невозможно присвоить несуществующему свойству "role_value"

Документация намекает на то, что ListElements можно определить только в ListModels. Насколько я знаю, это кажется единственным возможным решением. Это означает изменение свойства по умолчанию на list<ListModel> и изменение использования на

ListView {
    model: MyModel {
        // ListModel is auto-assigned to the default property
        ListModel {
            ListElement { role_value: "OTHER A" }
            ListElement { role_value: "OTHER B" }
            ListElement { role_value: "OTHER C" }
        }
    }
}

Вот минимальный и полный пример:

//  MyModel.qml
import QtQuick 2.0

ListModel {
    id: model
    default property list<ListModel> otherModels

    ListElement { role_value: "COMMON A" }
    ListElement { role_value: "COMMON B" }
    ListElement { role_value: "COMMON C" }

    //  called everytime a model is append to otherModels
    onOtherModelsChanged: {
        //  add ListElements from the last otherModels to this model
        var i = otherModels.length - 1;
        if (i < 0) return;

        for (var j = 0; j < otherModels[i].count; j++)
            model.append(otherModels[i].get(j));
    }
}


//  Main.qml
import QtQuick 2.6 
import QtQuick.Window 2.2      //  Window
import QtQuick.Controls 2.2    //  ItemDelegate

Window {
    visible: true
    width: 640
    height: 480

    ListView {
        anchors.fill: parent
        model: MyModel {
            ListModel {
                ListElement { role_value: "OTHER A" }
                ListElement { role_value: "OTHER B" }
                ListElement { role_value: "OTHER C" }
            }
        }

        delegate: ItemDelegate {
            text: role_value
            width: parent.width
        }
    }
}

См. Более сложную демонстрацию на Github.

default property list<ListModel> и реализация onOtherModelsChanged позволяет нескольким моделям "сцепляться" с базовой моделью.

Скриншот успеха:

enter image description here

Как отмечает augre , в случае, когда только одна одна модель когда-либо объединяется, вы можете упростить свойство до default property ListModel otherModel и иметь

onOtherModelChanged: {
    if (otherModel === undefined) return;
    for (var i = 0; i < otherModel.count; i++)
        model.append(otherModel.get(i));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...