Jak zaimplementować funkcję parent i index w QAbstractItemModel

0

Próbuję zrozumieć model QAbstractItemModel i jest tam zestaw funkcji do zaimplementowania. Najbardziej interesują mnie dwie funkcje

  1. index
virtual QModelIndex	index(int row, int column, const QModelIndex &parent = QModelIndex()) const = 0
  1. parent
virtual QModelIndex	parent(const QModelIndex &index) const = 0

Próbując zaimplementować model - napisałem taki kawałek kodu

#include "model.h"

Model::Model(QObject *parent) : QAbstractItemModel{parent}
{
    mainData = new QList<QString>;
    mainData->append("Dana nr 1");
    mainData->append("Dana nr 2");
    mainData->append("Dana nr 3");

    qInfo()<< "ptr mainData in Model" << mainData;
}

Model::~Model()
{

}

int Model::rowCount(const QModelIndex &parent) const
{
    quint32 row = mainData->count();
//    qInfo()<< static_cast<QList<QString>*>(parent.internalPointer())->count();
    return row;
}

int Model::columnCount(const QModelIndex &parent) const
{
    return 1;
}

QModelIndex Model::index(int row, int column, const QModelIndex &parent) const
{
    QModelIndex index = createIndex(row, column, mainData); //![1]

    return index;
}

QModelIndex Model::parent(const QModelIndex &index) const //pobiera rodzica przez model
{
    QModelIndex parent = createIndex(index.row(), index.column(), index.internalId());

    return parent;
}

QVariant Model::data(const QModelIndex &index, int role) const
{
    QVariant data;

    QList<QString> *listData = static_cast<QList<QString>*>(index.internalPointer());

    if(role == Qt::DisplayRole || role == Qt::EditRole){
        if(index.column()==0 && index.row()==0){
            data = listData->at(0);
            return data;
        }
        if(index.column()==0 && index.row()==1){
            data = listData->at(1);
            return data;
        }
        if(index.column()==0 && index.row()==2){
            data = listData->at(2);
            return data;
        }
    }

    return QVariant();
}

bool Model::setData(const QModelIndex &index, const QVariant &value, int role)
{
//    if(role == Qt::DisplayRole || role == Qt::EditRole){
//        qInfo()<< "role" << role;
//        return true;
//    }
    return true;
}

QVariant Model::headerData(int section, Qt::Orientation orientation, int role) const
{

    return QVariant();
}

Qt::ItemFlags Model::flags(const QModelIndex &index) const
{
    Qt::ItemFlags flag;

    return flag;
}

Więc pytanie jest takie
Jak zaimplementować funkcje index i parent wiedząc, że dane przechowuję w kontenerze QList<QString> który jest inicjalizowany w konstruktorze ?

Częściowo doszedłem, że w metodzie index muszę wykorzystać funkcję createIndex()

Czy ktoś mi pomoże i wyjaśni ten temat ?

3

Ani lista ani tabela nie są strukturami hierarchicznymi, więc żaden parent ich nie interesuje. Jeśli element listy/tabeli ma ustawionego rodzica to znaczy, że jest źle. Koniec kropka.

Jak to jest zaimplementowane dla listy to można sobie zobaczyć w źródłach Qt
link

QModelIndex QAbstractListModel::index(int row, int column, const QModelIndex &parent) const
{
    return hasIndex(row, column, parent) ? createIndex(row, column) : QModelIndex();
}

QModelIndex QAbstractListModel::parent(const QModelIndex & /* index */) const
{
    return QModelIndex();
}
0
tajny_agent napisał(a):

Ani lista ani tabela nie są strukturami hierarchicznymi, więc żaden parent ich nie interesuje.

Czy możesz powiedzieć co to znaczy "struktura hierarchiczna" ? Niby rozumiem ale wolałbym, żeby wypowiedział się ktoś, kto wie lepiej niż ja, bo nie chcę operować na "własnych pojęciach" tj. takich jak ja to rozumiem.

Jeśli element listy/tabeli ma ustawionego rodzica to znaczy, że jest źle. Koniec kropka.

Wiem, dlatego uważam, że adres "rodzica" to po prostu adres całej struktury danych. Czyli w przypadku kodu, który podałem powyżej, to adres rodzica byłby to adres obiektu mainData = new QList<QString>; - nie wiem czy dobrze myślę ?

miałbym jeszcze jedno pytanie - skąd funkcje rowCount i columnCount "pobierają" QModelIndex &parent ?
Czyżby ten parent "pochodził" funkcji QModelIndex Model::parent(const QModelIndex &index) const ? To znaczy, że najpierw muszą się wywołać funkcje index i parent aby te funkcje miały "informacje" o ilości kolumn i wierszy ?

0
zkubinski napisał(a):

Czy możesz powiedzieć co to znaczy "struktura hierarchiczna" ? Niby rozumiem ale wolałbym, żeby wypowiedział się ktoś, kto wie lepiej niż ja, bo nie chcę operować na "własnych pojęciach" tj. takich jak ja to rozumiem.

To znaczy, że istnienie jednego elementu jest zależne od istnienia innego elementu.

Wiem, dlatego uważam, że adres "rodzica" to po prostu adres całej struktury danych. Czyli w przypadku kodu, który podałem powyżej, to adres rodzica byłby to adres obiektu mainData = new QList<QString>; - nie wiem czy dobrze myślę ?

Nie mam pojęcia co masz na myśli pisząc "adres rodzica".

miałbym jeszcze jedno pytanie - skąd funkcje rowCount i columnCount "pobierają" QModelIndex &parent ?
Czyżby ten parent "pochodził" funkcji QModelIndex Model::parent(const QModelIndex &index) const ? To znaczy, że najpierw muszą się wywołać funkcje index i parent aby te funkcje miały "informacje" o ilości kolumn i wierszy ?

parent dostają z przeróżnych miejsc w których są wywoływane, głównie pewnie przez instancje widoków do których model jest podpięty. Ale to nie ma znaczenia. Te funkcje to publiczny interfejs klasy, więc może je wywołać dosłownie każdy.

0
tajny_agent napisał(a):

To znaczy, że istnienie jednego elementu jest zależne od istnienia innego elementu.

ok, to tak rozumiem

Wiem, dlatego uważam, że adres "rodzica" to po prostu adres całej struktury danych. Czyli w przypadku kodu, który podałem powyżej, to adres rodzica byłby to adres obiektu mainData = new QList<QString>; - nie wiem czy dobrze myślę ?

Nie mam pojęcia co masz na myśli pisząc "adres rodzica".

adres rodzica mam na myśli obiekt który został powołany do życia mainData = new QList<QString> natomiast dzieci będą to np mainData->append("Dana nr 1");

parent dostają z przeróżnych miejsc w których są wywoływane, głównie pewnie przez instancje widoków do których model jest podpięty. Ale to nie ma znaczenia. Te funkcje to publiczny interfejs klasy, więc może je wywołać dosłownie każdy.

rozumiem ale w argumencie funkcji jest int Model::rowCount(const QModelIndex &parent) const więc jak obsłużyć parent w tej funkcji ?

2
zkubinski napisał(a):

adres rodzica mam na myśli obiekt który został powołany do życia mainData = new QList<QString> natomiast dzieci będą to np mainData->append("Dana nr 1");

To nie ma związku. Skoro model reprezentuje listę, to nie ma mowy o rodzicu, bez względu na to czy dane trzymasz jako QList,std::vector czy cokolwiek innego.

rozumiem ale w argumencie funkcji jest int Model::rowCount(const QModelIndex &parent) const więc jak obsłużyć parent w tej funkcji ?

int ModelClass::rowCount(QModelIndex const& parent) const override
{
  return parent.isValid() ? 0 : mainData->size();
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1