diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp index c5201974..b42fcdd4 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp @@ -167,18 +167,34 @@ void QMLBackend::connectGrpcEvents() //**************************************************************************************************************************************************** void QMLBackend::retrieveUserList() { - QList users; - app().grpc().getUserList(users); + QList newUsers; + app().grpc().getUserList(newUsers); // As we want to use shared pointers here, we do not want to use the Qt ownership system, so we set parent to nil. // But: From https://doc.qt.io/qt-5/qtqml-cppintegration-data.html: // " When data is transferred from C++ to QML, the ownership of the data always remains with C++. The exception to this rule // is when a QObject is returned from an explicit C++ method call: in this case, the QML engine assumes ownership of the object. " // This is the case here, so we explicitly indicate that the object is owned by C++. - for (SPUser const& user: users) - QQmlEngine::setObjectOwnership(user.get(), QQmlEngine::CppOwnership); + for (SPUser const& user: newUsers) - users_->reset(users); + for (qsizetype i = 0; i < newUsers.size(); ++i) + { + SPUser newUser = newUsers[i]; + SPUser existingUser = users_->getUserWithID(newUser->id()); + if (!existingUser) + { + // The user is new. We indicate to QML that it is managed by the C++ backend. + QQmlEngine::setObjectOwnership(user.get(), QQmlEngine::CppOwnership); + continue; + } + + // The user is already listed. QML code may have a pointer because of an ongoing process (for instance in the SetupGuide), + // As a consequence we do not want to replace this existing user, but we want to update it. + existingUser->update(*newUser); + newUsers[i] = existingUser; + } + + users_->reset(newUsers); } diff --git a/internal/frontend/bridge-gui/bridge-gui/UserList.cpp b/internal/frontend/bridge-gui/bridge-gui/UserList.cpp index 8e822d71..9492c75c 100644 --- a/internal/frontend/bridge-gui/bridge-gui/UserList.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/UserList.cpp @@ -142,6 +142,19 @@ void UserList::updateUserAtRow(int row, User const &user) } +//**************************************************************************************************************************************************** +/// \param[in] userID The userID. +/// \return The user with the given ID. +/// \return A null pointer if the user could not be found. +//**************************************************************************************************************************************************** +bridgepp::SPUser UserList::getUserWithID(QString const &userID) const +{ + QList::const_iterator it = std::find_if(users_.begin(), users_.end(), [userID](SPUser const & user) -> bool { + return user && user->id() == userID; }); + return (it == users_.end()) ? nullptr : *it; +} + + //**************************************************************************************************************************************************** /// \param[in] row The row. //**************************************************************************************************************************************************** diff --git a/internal/frontend/bridge-gui/bridge-gui/UserList.h b/internal/frontend/bridge-gui/bridge-gui/UserList.h index afbd18b0..e4117af4 100644 --- a/internal/frontend/bridge-gui/bridge-gui/UserList.h +++ b/internal/frontend/bridge-gui/bridge-gui/UserList.h @@ -44,6 +44,7 @@ public: // member functions. void removeUserAt(int row); ///< Remove the user at a given row void appendUser(bridgepp::SPUser const &user); ///< Add a new user. void updateUserAtRow(int row, bridgepp::User const &user); ///< Update the user at given row. + bridgepp::SPUser getUserWithID(QString const& userID) const; ///< Retrieve the user with the given ID. // the userCount property. Q_PROPERTY(int count READ count NOTIFY countChanged)