Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QAbstractItemModel and DalegateModel.qml



  • Hello everyone!
    I'm developing telegram app for mobile with qt. Got a problem with list of stickers.
    Data structure is this:
    stickerSet object 1
    | sticker 1
    | sticker 2
    ...
    | sticker N
    stickerSet 2
    | sticker 1
    | sticker 2
    ..
    | sticker N

    code for sticker model on github here
    and qml file is here

    Problem: After calling dataChanged for sticker to update its filepath, model doesnt update. (ModelIndex for this item is saved in QMap)

    I'm assuming I created wrong qabstractitemmodel, but can't find correct example.
    Thanks in advance for any clue.


  • Moderators

    @blacky_i said in QAbstractItemModel and DalegateModel.qml:

    Problem: After calling dataChanged for sticker to update its filepath, model doesnt update. (ModelIndex for this item is saved in QMap)

    1. when do you can dataChanged()?
    2. storing QModelIndexes is always a bad idea

    To quickly verify your model implementation you can use ModelTest class (check the console output):

    #include <modeltest.h>
    
    MyModel *model = new MyModel(this);
    new ModelTest(model, this);
    


  • @raven-worx said in QAbstractItemModel and DalegateModel.qml:

    when do you can dataChanged()?

    After visualising image in qml. If image do not exists on device, data function emits signal to downloadFile from Telegram and stores its QmodelIndex for future update. MEssage from Telegram returns, it updates item in list and calls dataChanged(). But refresing item do not happening.


  • Moderators

    @blacky_i
    the problem with storing model indexes is that they are not meant to be stored, since they are only valid until the next model change.
    Try changing the QMap to use QPersistentModelIndexes instead (just changing the QMap declaration in the header should be enough) and check if works.

    Otherwise you will need to show a bit more code.



  • @raven-worx Oh, ok. I added links to github in first post, but I will duplicate as message.

    StickerModel.cpp

    #include "StickerModel.hpp"
    #include <QDebug>
    #include "tdlibQt/TdlibJsonWrapper.hpp"
    #include "tdlibQt/ParseObject.hpp"
    namespace tdlibQt {
    
    StickerModel::StickerModel(QObject *parent) : QAbstractItemModel(parent),
        m_client(TdlibJsonWrapper::instance())
    {
        connect(m_client, &TdlibJsonWrapper::stickerSetReceived,
                this, &StickerModel::addStickerSet);
        //BUG? Lambda functions requires disconnection before dectruction?. Even disconnection doesnt help
        connect(m_client, &TdlibJsonWrapper::stickerSetsReceived,
                this, &StickerModel::stickersSetsReceived);
        connect(m_client, &TdlibJsonWrapper::stickersReceived,
                this, &StickerModel::stickersReceived);
        connect(m_client, &TdlibJsonWrapper::updateFile,
                this, &StickerModel::updateFile);
    
        connect(this, &StickerModel::downloadFileStart,
                this, &StickerModel::getFile);
    
    }
    
    StickerModel::~StickerModel()
    {
        m_stikerSets.clear();
        m_installedStickerSets.clear();
    }
    
    void StickerModel::getAttachedStickerSets(const int file_id)
    {
        m_client->getAttachedStickerSets(file_id);
    }
    
    void StickerModel::getStickerSet(const qint64 set_id)
    {
        m_client->getStickerSet(set_id);
    }
    
    void StickerModel::getFavoriteStickers()
    {
        m_client->getFavoriteStickers();
    }
    
    void StickerModel::getRecentStickers()
    {
        m_client->getRecentStickers();
    }
    
    void StickerModel::getInstalledStickers(const bool is_masks)
    {
        m_client->getInstalledStickerSets(is_masks);
    }
    
    void StickerModel::addTrendingStickerSets(const QJsonObject &stickerSetsObject)
    {
        auto stickerSetsObj = ParseObject::parseStickerSets(stickerSetsObject);
        for (QSharedPointer<stickerSetInfo> val : stickerSetsObj->sets_)
            m_trendingStickerSets.append(val);
    }
    
    QSharedPointer<stickerSet> StickerModel::createStickerSet(const QString &name, const QString &title,
            const std::vector<QSharedPointer<sticker> > &stickers)
    {
        if (stickers.size() == 0)
            return QSharedPointer<stickerSet>(nullptr);
    
        QSharedPointer<stickerSet> resultSet = QSharedPointer<stickerSet>(new stickerSet);
        resultSet->name_ = name.toStdString();
        resultSet->title_ = title.toStdString();
        resultSet->stickers_ = stickers;
    
        return resultSet;
    }
    
    StickerModel::StickerModelState StickerModel::modelState() const
    {
        return m_state;
    }
    
    QHash<int, QByteArray> StickerModel::roleNames() const
    {
        QHash<int, QByteArray>  roles;
        roles[ID] = "id";
        roles[IS_ARCHIVED] = "is_archived";
        roles[IS_INSTALLED] = "is_installed";
        roles[IS_MASKS] = "is_masks";
        roles[IS_OFFICIAL] = "is_official";
        roles[IS_VIEWED] = "is_viewed";
        roles[TITLE] = "title";
        roles[NAME] = "name";
        roles[STICKER] = "sticker";
        roles[EMOJI] = "emoji";
        roles[STICKERS_COUNT] = "stickers_count";
        roles[SET_STICKER_THUMBNAIL] = "set_thumbnail";
    
        roles[STICKER_FILE_ID] = "sticker_file_id";
        return roles;
    }
    
    QVariant StickerModel::data(const QModelIndex &index, int role) const
    {
        if (!index.isValid())
            return QVariant();
    
        if (index.row() < 0)
            return QVariant();
    
        int rowIndex = index.row();
        int setNumber = index.parent().column() == -1 ? index.parent().row() : rowIndex;//getSetIndex(rowIndex);
        setNumber = setNumber == -1 ? rowIndex : setNumber;
        switch (role) {
        case ID:
            return  QString::number(m_stikerSets[setNumber]->id_);
        case IS_ARCHIVED:
            return    m_stikerSets[setNumber]->is_archived_;
        case IS_INSTALLED:
            return   m_stikerSets[setNumber]->is_installed_;
        case IS_MASKS:
            return    m_stikerSets[setNumber]->is_masks_;
        case IS_OFFICIAL:
            return    m_stikerSets[setNumber]->is_official_;
        case IS_VIEWED:
            return    m_stikerSets[setNumber]->is_viewed_;
        case TITLE:
            return   QString::fromStdString(m_stikerSets[setNumber]->title_);
        case NAME:
            return   QString::fromStdString(m_stikerSets[setNumber]->name_);
        case SET_STICKER_THUMBNAIL:
            return   QString::fromStdString(m_stikerSets[setNumber]->stickers_[0]->sticker_->local_->path_);
        case STICKERS_COUNT:
            return m_stikerSets[setNumber]->stickers_.size();
        case STICKER:
            if (index.parent().row() == -1)
                return QVariant();
            //    m_installedStickerSets[rowIndex]->covers_;
            if (m_stikerSets[setNumber]->stickers_[rowIndex]->sticker_->local_->is_downloading_completed_)
                return   QString::fromStdString(m_stikerSets[setNumber]->stickers_[rowIndex]->sticker_->local_->path_);
            if (m_stikerSets[setNumber]->stickers_[rowIndex]->thumbnail_->photo_->local_->is_downloading_completed_) {
                emit downloadFileStart(m_stikerSets[setNumber]->stickers_[rowIndex]->sticker_->id_, 12, index);
                return   QString::fromStdString(m_stikerSets[setNumber]->stickers_[rowIndex]->thumbnail_->photo_->local_->path_);
            }
            emit downloadFileStart(m_stikerSets[setNumber]->stickers_[rowIndex]->thumbnail_->photo_->id_, 12, index);
            return QVariant();
        case EMOJI: {
            if (index.parent().row() == -1)
                return QVariant();
    
            QString emojis = "";
            emojis += QString::fromStdString(m_stikerSets[setNumber]->stickers_[rowIndex]->emoji_);
            return emojis;
        }
        break;
        case STICKER_FILE_ID:
            if (index.parent().row() == -1)
                return QVariant();
            return m_stikerSets[setNumber]->stickers_[rowIndex]->sticker_->id_;
            break;
        default:
            return QVariant();
            break;
        }
    
        //    m_installedStickerSets[rowIndex]->id_;
        //    m_installedStickerSets[rowIndex]->is_archived_;
        //    m_installedStickerSets[rowIndex]->is_installed_;
        //    m_installedStickerSets[rowIndex]->is_masks_;
        //    m_installedStickerSets[rowIndex]->is_official_;
        //    m_installedStickerSets[rowIndex]->is_viewed_;
        //    m_installedStickerSets[rowIndex]->name_;
        //    m_installedStickerSets[rowIndex]->title_;
    
    
    }
    
    
    int StickerModel::rowCount(const QModelIndex &parent) const
    {
        if (m_state == SendState || m_state == PreviewState) {
            if (parent.column() == 0) {
                return m_stikerSets.at(parent.row())->stickers_.size();
            } else
                return m_stikerSets.size();
        }
    
        return 0;
    }
    
    
    void StickerModel::addInstalledStickerSets(const QJsonObject &stickerSetsObject)
    {
        auto stickerSetsObj = ParseObject::parseStickerSets(stickerSetsObject);
        for (QSharedPointer<stickerSetInfo> val : stickerSetsObj->sets_) {
            m_installedStickerSets.append(val);
            if (m_state == SendState)
                getStickerSet(val->id_);
        }
    }
    
    void StickerModel::addStickerSet(const QJsonObject &stickerSetObject)
    {
        auto stickerSetObj = ParseObject::parseStickerSet(stickerSetObject);
        if (stickerSetObj.data()) {
            beginInsertRows(QModelIndex(), m_stikerSets.size(), m_stikerSets.size());
            m_stikerSets.append(stickerSetObj);
            endInsertRows();
        }
    }
    
    void StickerModel::updateFile(const QJsonObject &fileObject)
    {
    
        if (fileObject["@type"].toString() == "updateFile")
            processFile(fileObject["file"].toObject());
    }
    
    void StickerModel::processFile(const QJsonObject &fileObject)
    {
    
        auto file = ParseObject::parseFile(fileObject);
        if (m_stickerUpdateQueue.keys().contains(file->id_)) {
            QVector<int> photoRole;
            QModelIndex viewIndex = m_stickerUpdateQueue[file->id_];
            qDebug() << viewIndex << "Row" << viewIndex.row() << "Column" << viewIndex.column() <<  viewIndex.parent().row();
    
            int rowIndex = viewIndex.row();
            int setIndex = viewIndex.parent().row();
    
            if (m_stikerSets[setIndex]->stickers_[rowIndex]->sticker_->id_ == file->id_)
                m_stikerSets[setIndex]->stickers_[rowIndex]->sticker_ = file;
            if (m_stikerSets[setIndex]->stickers_[rowIndex]->thumbnail_->photo_->id_ == file->id_)
                m_stikerSets[setIndex]->stickers_[rowIndex]->thumbnail_->photo_ = file;
            if (file->local_->is_downloading_completed_) {
                photoRole.append(STICKER);
                photoRole.append(SET_STICKER_THUMBNAIL);
                emit refreshSticker();
            }
            emit dataChanged(index(rowIndex, 0, index(setIndex, -1)),
                             index(rowIndex, 0, index(setIndex, -1)), photoRole);
            if (file->local_->is_downloading_completed_)
                m_stickerUpdateQueue.remove(file->id_);
        }
    
    }
    
    void StickerModel::stickersReceived(const QJsonObject &setObject)
    {
        if (setObject["@extra"].toString() == "getFavoriteStickers")
            addFavoriteStickers(setObject);
        else
            addRecentStickers(setObject);
    }
    
    void StickerModel::stickersSetsReceived(const QJsonObject &setsObject)
    {
        if (setsObject["@extra"].toString() == "getTrendingStickerSets")
            addTrendingStickerSets(setsObject);
        else
            addInstalledStickerSets(setsObject);
    }
    
    void StickerModel::changeStickerSet(const QString &setId, const bool isInstalled, const bool isArchived)
    {
        m_client->changeStickerSet(setId.toLongLong(), isInstalled, isArchived);
    }
    
    QVariant StickerModel::getStickerUrl(const int setIndex, const int stickerIndex)
    {
        return data(index(stickerIndex, 0, createIndex(setIndex, 0)), DataRoles::STICKER);
    }
    
    QVariant StickerModel::getStickerEmoji(const int setIndex, const int stickerIndex)
    {
        return data(index(stickerIndex, 0, createIndex(setIndex, 0)), DataRoles::EMOJI);
    }
    
    QVariant StickerModel::getStickersCount(const int setIndex)
    {
        return data(index(setIndex, 0), DataRoles::STICKERS_COUNT);
    }
    
    void StickerModel::setSet_id(QString set_id)
    {
        if (m_set_id == set_id)
            return;
    
        m_set_id = set_id;
        emit set_idChanged(m_set_id);
    }
    
    void StickerModel::getFile(const int fileId, const int priority, const QModelIndex indexItem)
    {
        m_client->downloadFile(fileId, priority);
        m_stickerUpdateQueue[fileId] = indexItem;
    
    }
    
    int StickerModel::columnCount(const QModelIndex &parent) const
    {
        return 1;
    }
    
    QModelIndex StickerModel::index(int row, int column, const QModelIndex &parent) const
    {
        if (!hasIndex(row, column, parent))
            return QModelIndex();
    
        if (parent.column() > -1)
            return createIndex(row, column, m_stikerSets.at(parent.row()).data());
        return createIndex(row, column);
    
    }
    
    QModelIndex StickerModel::parent(const QModelIndex &child) const
    {
        if (!child.isValid())
            return QModelIndex();
    
        stickerSet *childItem = static_cast<stickerSet *>(child.internalPointer());
        if (!childItem)
            return QModelIndex();
    
        if (child.column() == -1)
            return QModelIndex();
    
        int rowPosition = 0;
        for (int i = 0; i < m_stikerSets.size(); i++)
            if (m_stikerSets.at(i).data() == childItem) {
                rowPosition = i;
                break;
            }
        return createIndex(rowPosition, -1);
    }
    
    bool StickerModel::hasChildren(const QModelIndex &parent) const
    {
        return parent.column() == -1;
    }
    
    QString StickerModel::set_id() const
    {
        return m_set_id;
    }
    void StickerModel::addFavoriteStickers(const QJsonObject &stickersObject)
    {
        auto stickersObj = ParseObject::parseStickers(stickersObject);
        auto resultSet = createStickerSet("Favorite", tr("Favorite"), stickersObj->stickers_);
        if (resultSet.data()) {
            beginInsertRows(QModelIndex(), m_stikerSets.size(), m_stikerSets.size());
            m_stikerSets.append(resultSet);
            endInsertRows();
        }
    }
    
    void StickerModel::addRecentStickers(const QJsonObject &stickersObjecct)
    {
        auto stickersObj = ParseObject::parseStickers(stickersObjecct);
        auto resultSet = createStickerSet("Recent", tr("Recent"), stickersObj->stickers_);
    
        if (resultSet.data()) {
            beginInsertRows(QModelIndex(), m_stikerSets.size(),  m_stikerSets.size());
            m_stikerSets.append(resultSet);
            endInsertRows();
        }
    }
    
    void StickerModel::setModelState(StickerModel::StickerModelState state)
    {
        if (m_state == state)
            return;
    
        m_state = state;
        beginResetModel();
        m_stikerSets.clear();
        m_installedStickerSets.clear();
        endResetModel();
        switch (m_state) {
        case SendState:
            getFavoriteStickers();
            getRecentStickers();
            getInstalledStickers();
            break;
        case PreviewState:
            if (set_id().length() > 0)
                getStickerSet(set_id().toLongLong());
            break;
        case SettingsState:
    
        case TrendingState:
        default:
            break;
        }
        emit modelStateChanged(m_state);
    }
    } //tdlibQt
    

    PreviewStickerSetDialog.qml

    import QtQuick 2.0
    import Sailfish.Silica 1.0
    import tdlibQtEnums 1.0
    import TelegramModels 1.0
    import QtQml.Models 2.3
    import org.nemomobile.notifications 1.0
    import "../items"
    Dialog {
        id:rootPage
        property alias set_id: stickerModel.set_id
        property bool _previewEnabled: false
        property bool _setIsInstalled: false
        canAccept: !_previewEnabled
        states:[
            State {
                name: "general"
                PropertyChanges {
                    target: rootPage
                    _previewEnabled:false
                }
                PropertyChanges {
                    target: rootPage
                    backNavigation:true
                }
                PropertyChanges {
                    target: previewRect
                    visible:false
                }
    
            },
            State {
                name: "preview"
                PropertyChanges {
                    target: rootPage
                    _previewEnabled:true
                }
                PropertyChanges {
                    target: rootPage
                    backNavigation:false
                }
                PropertyChanges {
                    target: previewRect
                    visible:true
                }
                StateChangeScript {
                    name: "showNotification"
                    script: notificationPreviewMode.publish()
                }
    
            }
        ]
        state: "general"
        onAccepted: {
        if(_setIsInstalled)
            stickerModel.changeStickerSet(set_id,false)
        else
            stickerModel.changeStickerSet(set_id,true)
        }
    Notification {
        id:notificationPreviewMode
        appName: "Depecher"
        previewBody: qsTr("Sticker preview mode")
    }
    StickerModel {
        id:stickerModel
        modelState: set_id ==="" ? StickerModel.UknownState : StickerModel.PreviewState
    }
    
    
    MouseArea {
        id:previewArea
        enabled: _previewEnabled
        focus: _previewEnabled
        width: parent.width
        height: parent.height - header.height
        anchors.bottom: parent.bottom
        property var component
        property var previewItem
        preventStealing: true
        onPositionChanged: previewThis(mouseX,mouseY)
        onEnabledChanged: {
            if(enabled)
            {
                component = Qt.createComponent(Qt.resolvedUrl("../items/StickerPreviewComponent.qml"));
                previewItem = component.createObject(rootPage, {"source": undefined});
                previewItem.anchors.centerIn = rootPage
                previewItem.z = listView.z + 2
            }
            else {
                if(component)
                    component.destroy()
                if(previewItem)
                    previewItem.destroy()
            }
        }
    
        function previewThis(x,y) {
            //delegateModel do not get item through index
            //Thats why getting sticker url via model slot
            var stikerGridIndex =  listView.indexAt(x,y+listView.contentY)
            var grid =listView.itemAt(x,y+listView.contentY).gridSticker
            if (grid) {
                var previousHeight = 0;
                var indexItem = 0
                var setIndex = stikerGridIndex
                //Get height of all gridView previously
                indexItem = grid.indexAt(x,mapToItem(grid,x,y).y)
                var stickerUrl = listView.model.model.getStickerUrl(setIndex,indexItem);
                if(stickerUrl)
                {
                    previewItem.source = "image://depecherDb/"+stickerUrl;
                    previewItem.emoji = listView.model.model.getStickerEmoji(setIndex,indexItem);
                }
    
            }
        }
        onReleased: rootPage.state = "general"
    }
    Rectangle {
        id:previewRect
        visible: false
        parent: rootPage
        z:listView.z + 1
        anchors.fill: parent
        gradient: Gradient {
            GradientStop { position:  1.0; color: "transparent" }
            GradientStop { position:  0.0; color: Theme.highlightDimmerColor }
        }
    }
    Column {
        width:parent.width
    
    
    DialogHeader {
        id:header
        acceptText: rootPage._setIsInstalled ? qsTr("Remove %1 stickers").arg(listView.contentItem.children[0].gridSticker.count) :qsTr("Add %1 stickers").arg(listView.contentItem.children[0].gridSticker.count)
        cancelText: qsTr("Back")
    }
            SilicaListView {
                id:listView
                width: parent.width
                height: rootPage.height - header.height
                clip:true
                interactive: !_previewEnabled
                onFlickingChanged: previewTimer.stop()
                model:  DelegateModel {
                    id:stickerSetModel
                    model: stickerModel
                    delegate: Item {
                        width: parent.width
                        height: columnStickers.height
                        property alias itemIndex: stickersGrid
                        property alias gridSticker: stickersGrid
                        property alias stickersCount: stickersGrid.count
                        Column {
                            id:columnStickers
                            width: parent.width
                            height: sectionHeader.height + stickersGrid.height
                            SectionHeader {
                                id:sectionHeader
                                text:title
                            }
                            DelegateModel {
                                id:stickers
                                model: stickerModel
                                rootIndex:listView.model.modelIndex(index)
    
    
                                delegate: Image {
                                    width: stickersGrid.cellWidth
                                    height: width
                                    asynchronous: true
                                    fillMode: Image.PreserveAspectFit
                                    source: "image://depecherDb/" + sticker
                                    Connections {
                                        target: stickerModel
                                        onRefreshSticker:{
    stickersGrid.forceLayout()
                                        }
                                    }
                                    MouseArea {
                                        anchors.fill: parent
                                        enabled: !_previewEnabled
                                        onPressed:{
                                            previewTimer.start()
                                        }
                                        onClicked:  {
                                            if( rootPage.state === "general")
                                                sendUrlItems([{"id":sticker_file_id,"type":TdlibState.Sticker,"url":sticker}])
    
                                        }
                                        onExited: {
                                            if(previewTimer.running)
                                                previewTimer.stop()
                                        }
                                    }
                                }
                            }
                            SilicaGridView {
                                id:stickersGrid
                                width: parent.width
                                interactive: !_previewEnabled
                                cellWidth: parent.width/5
                                cellHeight: cellWidth
                                height:Math.ceil(count / 5) * cellHeight
                                model:stickers
                            }
                        }
                    Component.onCompleted:{
                        rootPage._setIsInstalled = is_installed
                    }
                    }
                }
    
    
            }
    }
    
            Timer {
                id:previewTimer
                interval: 800
                onTriggered:                 rootPage.state = "preview"
            }
    }
    

  • Moderators

    @blacky_i said in QAbstractItemModel and DalegateModel.qml:

    Oh, ok. I added links to github in first post, but I will duplicate as message.

    i thought you applied custom changes to the code? I assumed you are using 3rd party code.



  • @raven-worx Many thanks! ModelTest did help. I resloved all Q_ASSERT and model updates fine!) You saved me many nights.

    Posting code which works fine:

    #include "StickerModel.hpp"
    #include <QDebug>
    #include "tdlibQt/TdlibJsonWrapper.hpp"
    #include "tdlibQt/ParseObject.hpp"
    namespace tdlibQt {
    
    StickerModel::StickerModel(QObject *parent) : QAbstractItemModel(parent),
        m_client(TdlibJsonWrapper::instance())
    {
        rootSet =     QSharedPointer<stickerSet>(new stickerSet);
        connect(m_client, &TdlibJsonWrapper::stickerSetReceived,
                this, &StickerModel::addStickerSet);
        //BUG? Lambda functions requires disconnection before dectruction?. Even disconnection doesnt help
        connect(m_client, &TdlibJsonWrapper::stickerSetsReceived,
                this, &StickerModel::stickersSetsReceived);
        connect(m_client, &TdlibJsonWrapper::stickersReceived,
                this, &StickerModel::stickersReceived);
        connect(m_client, &TdlibJsonWrapper::updateFile,
                this, &StickerModel::updateFile);
    
        connect(this, &StickerModel::downloadFileStart,
                this, &StickerModel::getFile);
    
    }
    
    StickerModel::~StickerModel()
    {
        m_stikerSets.clear();
        m_installedStickerSets.clear();
    }
    
    void StickerModel::getAttachedStickerSets(const int file_id)
    {
        m_client->getAttachedStickerSets(file_id);
    }
    
    void StickerModel::getStickerSet(const qint64 set_id)
    {
        m_client->getStickerSet(set_id);
    }
    
    void StickerModel::getFavoriteStickers()
    {
        m_client->getFavoriteStickers();
    }
    
    void StickerModel::getRecentStickers()
    {
        m_client->getRecentStickers();
    }
    
    void StickerModel::getInstalledStickers(const bool is_masks)
    {
        m_client->getInstalledStickerSets(is_masks);
    }
    
    void StickerModel::addTrendingStickerSets(const QJsonObject &stickerSetsObject)
    {
        auto stickerSetsObj = ParseObject::parseStickerSets(stickerSetsObject);
        for (QSharedPointer<stickerSetInfo> val : stickerSetsObj->sets_)
            m_trendingStickerSets.append(val);
    }
    
    QSharedPointer<stickerSet> StickerModel::createStickerSet(const QString &name, const QString &title,
            const std::vector<QSharedPointer<sticker> > &stickers)
    {
        if (stickers.size() == 0)
            return QSharedPointer<stickerSet>(nullptr);
    
        QSharedPointer<stickerSet> resultSet = QSharedPointer<stickerSet>(new stickerSet);
        resultSet->name_ = name.toStdString();
        resultSet->title_ = title.toStdString();
        resultSet->stickers_ = stickers;
    
        return resultSet;
    }
    
    StickerModel::StickerModelState StickerModel::modelState() const
    {
        return m_state;
    }
    
    QHash<int, QByteArray> StickerModel::roleNames() const
    {
        QHash<int, QByteArray>  roles;
        roles[ID] = "id";
        roles[IS_ARCHIVED] = "is_archived";
        roles[IS_INSTALLED] = "is_installed";
        roles[IS_MASKS] = "is_masks";
        roles[IS_OFFICIAL] = "is_official";
        roles[IS_VIEWED] = "is_viewed";
        roles[TITLE] = "title";
        roles[NAME] = "name";
        roles[STICKER] = "sticker";
        roles[EMOJI] = "emoji";
        roles[STICKERS_COUNT] = "stickers_count";
        roles[SET_STICKER_THUMBNAIL] = "set_thumbnail";
    
        roles[STICKER_FILE_ID] = "sticker_file_id";
        return roles;
    }
    
    QVariant StickerModel::data(const QModelIndex &index, int role) const
    {
        if (!index.isValid())
            return QVariant();
    
        if (index.row() < 0)
            return QVariant();
        stickerSet *childItem = static_cast<stickerSet *>(index.internalPointer());
        if (!childItem)
            return QVariant();
    
        int rowIndex = index.row();
        int setNumber = 0;//index.parent().column() == 0 ? index.parent().row() : rowIndex;//getSetIndex(rowIndex);
        if (childItem == rootSet.data()) {
            setNumber = index.row();
            rowIndex = index.row();
        } else {
            setNumber = index.parent().row();
            rowIndex = index.row();
        }
        switch (role) {
        case ID:
            return  QString::number(m_stikerSets[setNumber]->id_);
        case IS_ARCHIVED:
            return    m_stikerSets[setNumber]->is_archived_;
        case IS_INSTALLED:
            return   m_stikerSets[setNumber]->is_installed_;
        case IS_MASKS:
            return    m_stikerSets[setNumber]->is_masks_;
        case IS_OFFICIAL:
            return    m_stikerSets[setNumber]->is_official_;
        case IS_VIEWED:
            return    m_stikerSets[setNumber]->is_viewed_;
        case TITLE:
            return   QString::fromStdString(m_stikerSets[setNumber]->title_);
        case NAME:
            return   QString::fromStdString(m_stikerSets[setNumber]->name_);
        case SET_STICKER_THUMBNAIL:
            return   QString::fromStdString(m_stikerSets[setNumber]->stickers_[0]->sticker_->local_->path_);
        case STICKERS_COUNT:
            return m_stikerSets[setNumber]->stickers_.size();
        case STICKER:
            if (index.parent().row() == -1)
                return QVariant();
            //    m_installedStickerSets[rowIndex]->covers_;
            if (m_stikerSets[setNumber]->stickers_[rowIndex]->sticker_->local_->is_downloading_completed_)
                return   QString::fromStdString(m_stikerSets[setNumber]->stickers_[rowIndex]->sticker_->local_->path_);
            if (m_stikerSets[setNumber]->stickers_[rowIndex]->thumbnail_->photo_->local_->is_downloading_completed_) {
                emit downloadFileStart(m_stikerSets[setNumber]->stickers_[rowIndex]->sticker_->id_, 12, index);
                return   QString::fromStdString(m_stikerSets[setNumber]->stickers_[rowIndex]->thumbnail_->photo_->local_->path_);
            }
            emit downloadFileStart(m_stikerSets[setNumber]->stickers_[rowIndex]->thumbnail_->photo_->id_, 12, index);
            return QVariant();
        case EMOJI: {
            if (index.parent().row() == -1)
                return QVariant();
    
            QString emojis = "";
            emojis += QString::fromStdString(m_stikerSets[setNumber]->stickers_[rowIndex]->emoji_);
            return emojis;
        }
        break;
        case STICKER_FILE_ID:
            if (index.parent().row() == -1)
                return QVariant();
            return m_stikerSets[setNumber]->stickers_[rowIndex]->sticker_->id_;
            break;
        default:
            return QVariant();
            break;
        }
    
        //    m_installedStickerSets[rowIndex]->id_;
        //    m_installedStickerSets[rowIndex]->is_archived_;
        //    m_installedStickerSets[rowIndex]->is_installed_;
        //    m_installedStickerSets[rowIndex]->is_masks_;
        //    m_installedStickerSets[rowIndex]->is_official_;
        //    m_installedStickerSets[rowIndex]->is_viewed_;
        //    m_installedStickerSets[rowIndex]->name_;
        //    m_installedStickerSets[rowIndex]->title_;
    
    
    }
    
    
    int StickerModel::rowCount(const QModelIndex &parent) const
    {
        if (m_state == SendState || m_state == PreviewState) {
            stickerSet *childItem = static_cast<stickerSet *>(parent.internalPointer());
            if (parent == QModelIndex())
                return m_stikerSets.size();
    
            if (childItem == rootSet.data()) {
                return m_stikerSets.at(parent.row())->stickers_.size();
            } else
                return 0;
        }
    
        return 0;
    }
    
    
    void StickerModel::addInstalledStickerSets(const QJsonObject &stickerSetsObject)
    {
        auto stickerSetsObj = ParseObject::parseStickerSets(stickerSetsObject);
        for (QSharedPointer<stickerSetInfo> val : stickerSetsObj->sets_) {
            m_installedStickerSets.append(val);
            if (m_state == SendState)
                getStickerSet(val->id_);
        }
    }
    
    void StickerModel::addStickerSet(const QJsonObject &stickerSetObject)
    {
        auto stickerSetObj = ParseObject::parseStickerSet(stickerSetObject);
        if (stickerSetObj.data()) {
            beginInsertRows(QModelIndex(), m_stikerSets.size(), m_stikerSets.size());
            m_stikerSets.append(stickerSetObj);
            endInsertRows();
        }
    }
    
    void StickerModel::updateFile(const QJsonObject &fileObject)
    {
    
        if (fileObject["@type"].toString() == "updateFile")
            processFile(fileObject["file"].toObject());
    }
    
    void StickerModel::processFile(const QJsonObject &fileObject)
    {
    
        auto file = ParseObject::parseFile(fileObject);
        if (m_stickerUpdateQueue.keys().contains(file->id_)) {
            QVector<int> photoRole;
            QPersistentModelIndex viewIndex = m_stickerUpdateQueue[file->id_];
            qDebug() << viewIndex << "Row" << viewIndex.row() << "Column" << viewIndex.column() <<  viewIndex.parent().row();
    
            int rowIndex = viewIndex.row();
            int setIndex = viewIndex.parent().row();
    
            if (m_stikerSets[setIndex]->stickers_[rowIndex]->sticker_->id_ == file->id_)
                m_stikerSets[setIndex]->stickers_[rowIndex]->sticker_ = file;
            if (m_stikerSets[setIndex]->stickers_[rowIndex]->thumbnail_->photo_->id_ == file->id_)
                m_stikerSets[setIndex]->stickers_[rowIndex]->thumbnail_->photo_ = file;
            if (file->local_->is_downloading_completed_) {
                photoRole.append(STICKER);
                photoRole.append(SET_STICKER_THUMBNAIL);
            }
            //For child item
            emit dataChanged(viewIndex,
                             viewIndex, photoRole);
            //for thumbnails
            emit dataChanged(viewIndex.parent(),
                             viewIndex.parent(), photoRole);
            if (file->local_->is_downloading_completed_)
                m_stickerUpdateQueue.remove(file->id_);
        }
    
    }
    
    void StickerModel::stickersReceived(const QJsonObject &setObject)
    {
        if (setObject["@extra"].toString() == "getFavoriteStickers")
            addFavoriteStickers(setObject);
        else
            addRecentStickers(setObject);
    }
    
    void StickerModel::stickersSetsReceived(const QJsonObject &setsObject)
    {
        if (setsObject["@extra"].toString() == "getTrendingStickerSets")
            addTrendingStickerSets(setsObject);
        else
            addInstalledStickerSets(setsObject);
    }
    
    void StickerModel::changeStickerSet(const QString &setId, const bool isInstalled, const bool isArchived)
    {
        m_client->changeStickerSet(setId.toLongLong(), isInstalled, isArchived);
    }
    
    QVariant StickerModel::getStickerUrl(const int setIndex, const int stickerIndex)
    {
        return data(index(stickerIndex, 0, index(setIndex, 0)), DataRoles::STICKER);
    }
    
    QVariant StickerModel::getStickerEmoji(const int setIndex, const int stickerIndex)
    {
        return data(index(stickerIndex, 0, index(setIndex, 0)), DataRoles::EMOJI);
    }
    
    QVariant StickerModel::getStickersCount(const int setIndex)
    {
        return data(index(setIndex, 0), DataRoles::STICKERS_COUNT);
    }
    
    void StickerModel::setSet_id(QString set_id)
    {
        if (m_set_id == set_id)
            return;
    
        m_set_id = set_id;
        emit set_idChanged(m_set_id);
    }
    
    void StickerModel::getFile(const int fileId, const int priority, const QModelIndex indexItem)
    {
        m_client->downloadFile(fileId, priority);
        m_stickerUpdateQueue[fileId] = indexItem;
    
    }
    
    int StickerModel::columnCount(const QModelIndex &parent) const
    {
        return 1;
    }
    
    QModelIndex StickerModel::index(int row, int column, const QModelIndex &parent) const
    {
        if (!hasIndex(row, column, parent))
            return QModelIndex();
    
        if (parent.column() > -1)
            return createIndex(row, column, m_stikerSets.at(parent.row()).data());
        return createIndex(row, column, rootSet.data());
    
    }
    
    QModelIndex StickerModel::parent(const QModelIndex &child) const
    {
        if (!child.isValid())
            return QModelIndex();
    
        stickerSet *childItem = static_cast<stickerSet *>(child.internalPointer());
        if (!childItem)
            return QModelIndex();
    
        if (childItem == rootSet.data())
            return QModelIndex();
    
        if (child.column() == -1)
            return QModelIndex();
    
        int rowPosition = 0;
        for (int i = 0; i < m_stikerSets.size(); i++)
            if (m_stikerSets.at(i).data() == childItem) {
                rowPosition = i;
                break;
            }
        return createIndex(rowPosition, 0, rootSet.data());
    }
    
    bool StickerModel::hasChildren(const QModelIndex &parent) const
    {
        if (rowCount(parent) == 0)
            return false;
    
        return true;
    }
    
    QString StickerModel::set_id() const
    {
        return m_set_id;
    }
    void StickerModel::addFavoriteStickers(const QJsonObject &stickersObject)
    {
        auto stickersObj = ParseObject::parseStickers(stickersObject);
        auto resultSet = createStickerSet("Favorite", tr("Favorite"), stickersObj->stickers_);
        if (resultSet.data()) {
            beginInsertRows(QModelIndex(), m_stikerSets.size(), m_stikerSets.size());
            m_stikerSets.append(resultSet);
            endInsertRows();
        }
    }
    
    void StickerModel::addRecentStickers(const QJsonObject &stickersObjecct)
    {
        auto stickersObj = ParseObject::parseStickers(stickersObjecct);
        auto resultSet = createStickerSet("Recent", tr("Recent"), stickersObj->stickers_);
    
        if (resultSet.data()) {
            beginInsertRows(QModelIndex(), m_stikerSets.size(),  m_stikerSets.size());
            m_stikerSets.append(resultSet);
            endInsertRows();
        }
    }
    
    void StickerModel::setModelState(StickerModel::StickerModelState state)
    {
        if (m_state == state)
            return;
    
        m_state = state;
        beginResetModel();
        m_stikerSets.clear();
        m_installedStickerSets.clear();
        endResetModel();
        switch (m_state) {
        case SendState:
            getFavoriteStickers();
            getRecentStickers();
            getInstalledStickers();
            break;
        case PreviewState:
            if (set_id().length() > 0)
                getStickerSet(set_id().toLongLong());
            break;
        case SettingsState:
    
        case TrendingState:
        default:
            break;
        }
        emit modelStateChanged(m_state);
    }
    } //tdlibQt
    
    

    Also, to ensure that ModelTest work, I created rootContext as single model and opened qml page with this model to make ModelTest work. Resolving each seg fault resolved issue