0

I implemented my own Model for a list of users that are present in a channel.That works fine if the model is filled an the data is read, what does not work is live updates, if something new is added, it shows up only after a resize event.

bool UserModel::insertUser( QString channelId, QSharedPointer<RocketChatUser> user )
{
    auto values =  userMap.values( channelId );
    int index = values.count();
    auto qIndex = QModelIndex();
    if ( channelId == current ) {
        beginInsertRows( qIndex, index, index );
    }

    userMap.insert( channelId, user );

    if ( channelId == current ) {
        endInsertRows();
    }
}


class UserModel: public QAbstractListModel
{
    Q_OBJECT
    Q_PROPERTY(QString currentChannel READ getCurrent WRITE setCurrent NOTIFY currentChannelChanged)
    enum UserRoles {
          UserName = Qt::UserRole + 1,
          UserId
      };
public:
    UserModel( QObject *parent = 0 );
    int rowCount( const QModelIndex &parent = QModelIndex() ) const;
    QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const;
    bool insertUser(QString,QSharedPointer<RocketChatUser>);
    QString getCurrent() const;
    void setCurrent(const QString &value);
    void onCurrentChannelChanged(const QString &newText);

protected:
    QHash<int, QByteArray> roleNames() const;
    QSet<QString> duplicateCheck;
    QMultiMap<QString, QSharedPointer<RocketChatUser>> userMap;
    QString current;
signals:
    void currentChannelChanged(const QString &newText);
};

Current channel exists to store all users in the multimap whose key is the id of the channel and to return only those who belong to the channel for performance reasons.

It is created this way:

UserModel userModel;
context->setContextProperty("userModel",&userModel);

And QML look like this:

Drawer {
    z: 9
    width: Math.min(window.width, window.height) / 3 * 2
    height: window.height
    edge: Qt.LeftEdge
    ListView {
        anchors.fill: parent
        spacing: 1
        header: ToolBar {
            Text {
                text: qsTr("Users in channel")
                anchors.centerIn: parent
            }
            width: parent.width - 1
        }
        id: userListView
        model: userModel
        delegate: RowLayout {
        width: parent.width
        Button {
            anchors.fill: parent
            text: model.username
        }
        /*BusyIndicator{
                    id: loadingUserIndicator
                                anchors.centerIn: parent
                                        }*/
        }
        Component.onCompleted: {
            userModel.currentChannel = channelView.currentChannel
        }
    }
}
Adrien Leravat
  • 2,731
  • 18
  • 32
Dennis Beier
  • 363
  • 3
  • 14
  • The only thing to note in this few lines of code is that `*InsertRows` should always be called if you edit the backing data structure, as clearly described in the documentation [here](http://doc.qt.io/qt-5/qabstractitemmodel.html#subclassing). – BaCaRoZzo Mar 26 '17 at 00:43
  • Your `userModel` is not a local variable right ? Or is in your main ? Because I think you know what happens if it was to go out of scope. I guess your `rowCount` is working ok ? – Adrien Leravat Mar 26 '17 at 15:04
  • One problem is likely that you are signalling an "add row" at the end of the view but you are not necessarily adding the data at the end. You could try with emitting the correct insertion position – Kevin Krammer Mar 27 '17 at 08:55

0 Answers0