From aba0ffa581e025a6c2b1e89fd75d91cc2c81078b Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 23 Mar 2023 17:04:22 +0100 Subject: [PATCH] finished the system to perform lighter updates of channels --- .../gxschannels/GxsChannelPostFilesModel.cpp | 46 ++++- .../gxschannels/GxsChannelPostFilesModel.h | 86 ++++----- .../gui/gxschannels/GxsChannelPostsModel.cpp | 169 ++++++------------ .../gui/gxschannels/GxsChannelPostsModel.h | 7 +- .../GxsChannelPostsWidgetWithModel.cpp | 53 +++++- 5 files changed, 193 insertions(+), 168 deletions(-) diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostFilesModel.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelPostFilesModel.cpp index 78748bcbe..2d0b10106 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostFilesModel.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostFilesModel.cpp @@ -463,7 +463,49 @@ void RsGxsChannelPostFilesModel::setFiles(const std::list & postMods(); } -void RsGxsChannelPostFilesModel::update_files(const std::set& added_files,const std::set& removed_files) +void RsGxsChannelPostFilesModel::update_files(std::set& added_files,std::set& removed_files) { -#error TODO + // 1 - remove common files from both lists + + std::cerr << "RsGxsChannelPostsFilesModel:: updating files." << std::endl; + + for(auto afit=added_files.begin();afit!=added_files.end();) + { + auto rfit = removed_files.find(*afit); + + if(rfit != removed_files.end()) + { + std::cerr << " Eliminating common file " << rfit->mName << std::endl; + removed_files.erase(rfit); + auto tmp = afit; + ++tmp; + added_files.erase(afit); + afit = tmp; + } + else + ++afit; + } + + // 2 - add whatever file remains, + + for(const auto& f:removed_files) + { + std::cerr << " Removing deleted file " << f.mName << std::endl; + + for(uint32_t i=0;i& files); + void setFiles(const std::list& files); void setFilter(const QStringList &strings, uint32_t &count) ; // This method adds/removes the given lists of files. Useful when a single post is updated - void update_files(const std::set& added_files,const std::set& removed_files); + void update_files(std::set &added_files, std::set &removed_files); #ifdef TODO - QModelIndex getIndexOfFile(const RsFileHash& hash) const; + QModelIndex getIndexOfFile(const RsFileHash& hash) const; void setSortMode(SortMode mode) ; - void setTextColorRead (QColor color) { mTextColorRead = color;} - void setTextColorUnread (QColor color) { mTextColorUnread = color;} - void setTextColorUnreadChildren(QColor color) { mTextColorUnreadChildren = color;} - void setTextColorNotSubscribed (QColor color) { mTextColorNotSubscribed = color;} - void setTextColorMissing (QColor color) { mTextColorMissing = color;} - void setAuthorOpinion(const QModelIndex& indx,RsOpinion op); + void setTextColorRead (QColor color) { mTextColorRead = color;} + void setTextColorUnread (QColor color) { mTextColorUnread = color;} + void setTextColorUnreadChildren(QColor color) { mTextColorUnreadChildren = color;} + void setTextColorNotSubscribed (QColor color) { mTextColorNotSubscribed = color;} + void setTextColorMissing (QColor color) { mTextColorMissing = color;} + void setAuthorOpinion(const QModelIndex& indx,RsOpinion op); #endif // Helper functions @@ -115,25 +115,25 @@ public: Qt::ItemFlags flags(const QModelIndex& index) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; // Custom item roles QVariant sizeHintRole (int col) const; - QVariant displayRole (const ChannelPostFileInfo& fmpe, int col) const; - QVariant toolTipRole (const ChannelPostFileInfo& fmpe, int col) const; - QVariant userRole (const ChannelPostFileInfo& fmpe, int col) const; - QVariant sortRole (const ChannelPostFileInfo& fmpe, int col) const; - QVariant filterRole (const ChannelPostFileInfo& fmpe, int col) const; + QVariant displayRole (const ChannelPostFileInfo& fmpe, int col) const; + QVariant toolTipRole (const ChannelPostFileInfo& fmpe, int col) const; + QVariant userRole (const ChannelPostFileInfo& fmpe, int col) const; + QVariant sortRole (const ChannelPostFileInfo& fmpe, int col) const; + QVariant filterRole (const ChannelPostFileInfo& fmpe, int col) const; #ifdef TODO - QVariant decorationRole(const ForumModelPostEntry& fmpe, int col) const; - QVariant pinnedRole (const ForumModelPostEntry& fmpe, int col) const; - QVariant missingRole (const ForumModelPostEntry& fmpe, int col) const; - QVariant statusRole (const ForumModelPostEntry& fmpe, int col) const; - QVariant authorRole (const ForumModelPostEntry& fmpe, int col) const; - QVariant fontRole (const ForumModelPostEntry& fmpe, int col) const; - QVariant textColorRole (const ForumModelPostEntry& fmpe, int col) const; - QVariant backgroundRole(const ForumModelPostEntry& fmpe, int col) const; + QVariant decorationRole(const ForumModelPostEntry& fmpe, int col) const; + QVariant pinnedRole (const ForumModelPostEntry& fmpe, int col) const; + QVariant missingRole (const ForumModelPostEntry& fmpe, int col) const; + QVariant statusRole (const ForumModelPostEntry& fmpe, int col) const; + QVariant authorRole (const ForumModelPostEntry& fmpe, int col) const; + QVariant fontRole (const ForumModelPostEntry& fmpe, int col) const; + QVariant textColorRole (const ForumModelPostEntry& fmpe, int col) const; + QVariant backgroundRole(const ForumModelPostEntry& fmpe, int col) const; #endif /*! @@ -154,20 +154,20 @@ private: bool mFilteringEnabled; SortMode mSortMode; #endif - void preMods() ; - void postMods() ; + void preMods() ; + void postMods() ; quintptr getParentRow(quintptr ref,int& row) const; quintptr getChildRef(quintptr ref, int index) const; int getChildrenCount(quintptr ref) const; static bool convertTabEntryToRefPointer(uint32_t entry, quintptr& ref); - static bool convertRefPointerToTabEntry(quintptr ref,uint32_t& entry); + static bool convertRefPointerToTabEntry(quintptr ref,uint32_t& entry); #ifdef TODO - static void generateMissingItem(const RsGxsMessageId &msgId,ChannelPostsModelPostEntry& entry); + static void generateMissingItem(const RsGxsMessageId &msgId,ChannelPostsModelPostEntry& entry); #endif - void initEmptyHierarchy(); + void initEmptyHierarchy(); std::vector mFilteredFiles ; // store the list of files for the post std::vector mFiles ; // store the list of files for the post diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp index 425f39a1b..4f3223186 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp @@ -64,7 +64,7 @@ void RsGxsChannelPostsModel::setMode(TreeMode mode) triggerViewUpdate(); } -void updateCommentCounts( std::vector& posts, std::vector& comments) +void RsGxsChannelPostsModel::computeCommentCounts( std::vector& posts, std::vector& comments) { // Store posts IDs in a std::map to avoid a quadratic cost @@ -463,47 +463,73 @@ bool operator<(const RsGxsChannelPost& p1,const RsGxsChannelPost& p2) return p1.mMeta.mPublishTs > p2.mMeta.mPublishTs; } -void RsGxsChannelPostsModel::setSinglePost(const RsGxsChannelGroup& group, const RsGxsChannelPost& post) +void RsGxsChannelPostsModel::updateSinglePost(const RsGxsChannelPost& post,std::set& added_files,std::set& removed_files) { - if(mChannelGroup.mMeta.mGroupId != group.mMeta.mGroupId) - return; +#ifdef DEBUG_CHANNEL_MODEL + RsDbg() << "updating single post for group id=" << currentGroupId() << " and msg id=" << post.mMeta.mMsgId ; +#endif + added_files.clear(); + removed_files.clear(); - preMods(); + emit layoutAboutToBeChanged(); - // This is potentially quadratic, so it should not be called many times! + // linear search. Not good at all, but normally this is just for a single post. - bool found=false; + bool found = false; + const auto& new_post_meta(post.mMeta); - for(auto& p:mPosts) - if(post.mMeta.mMsgId == p.mMeta.mMsgId || post.mMeta.mOrigMsgId == p.mMeta.mMsgId) + for(uint32_t j=0;j0) - { - beginInsertRows(QModelIndex(),0,rowCount()-1); - endInsertRows(); + // We don't do that, because otherwise the filtered posts will be changed dynamically when browsing, which is bad. + // + // mFilteredPosts.clear(); + // for(uint32_t i=0;i& posts) { preMods(); @@ -533,96 +559,7 @@ void RsGxsChannelPostsModel::setPosts(const RsGxsChannelGroup& group, std::vecto emit channelPostsLoaded(); } -void RsGxsChannelPostsModel::update_single_post(const RsGxsMessageId& msg_id,std::set& added_files,std::set& removed_files) -{ -#ifdef DEBUG_CHANNEL_MODEL - RsDbg() << "updating single post for group id=" << currentGroupId() << " and msg id=" << msg_id ; -#endif - RsThread::async([this,&added_files,&removed_files, msg_id]() - { - // 1 - get message data from p3GxsChannels. No need for pointers here, because we send only a single post to postToObject() - // At this point we dont know what kind of msg id we have. It can be a vote, a comment or an actual message. - std::vector posts; - std::vector comments; - std::vector votes; - - if(!rsGxsChannels->getChannelContent(currentGroupId(), { msg_id }, posts,comments,votes) || posts.size() != 1) - { - RsErr() << " failed to retrieve channel message data for channel/msg " << currentGroupId() << "/" << msg_id ; - return; - } - - // Need to call this in order to get the actual comment count. The previous call only retrieves the message, since we supplied the message ID. - // another way to go would be to save the comment ids of the existing message and re-insert them before calling getChannelContent. - - if(!rsGxsChannels->getChannelComments(currentGroupId(),{ msg_id },comments)) - { - RsErr() << " failed to retrieve message comment data for channel/msg " << currentGroupId() << "/" << msg_id ; - return; - } - - // Normally, there's a single post in the "post" array. The function below takes a full array of posts however. - - updateCommentCounts(posts,comments); - - // 2 - update the model in the UI thread. - - added_files.clear(); - removed_files.clear(); - - RsQThreadUtils::postToObject( [&posts,&added_files,&removed_files,this]() - { - for(uint32_t i=0;i& posts, std::vector& comments); QModelIndex root() const{ return createIndex(0,0,(void*)NULL) ;} QModelIndex getIndexOfMessage(const RsGxsMessageId& mid) const; @@ -214,8 +215,6 @@ private: static void computeReputationLevel(uint32_t forum_sign_flags, RsGxsChannelPost& entry); void update_posts(const RsGxsGroupId& group_id); -public: - void update_single_post(const RsGxsMessageId& msgId, std::set &added_files, std::set &removed_files); private: @@ -235,7 +234,9 @@ private: //void computeMessagesHierarchy(const RsGxsChannelGroup& forum_group, const std::vector &msgs_array, std::vector &posts, std::map > > &mPostVersions); void createPostsArray(std::vector &posts); void setPosts(const RsGxsChannelGroup& group, std::vector &posts); - void setSinglePost(const RsGxsChannelGroup& group, const RsGxsChannelPost& post); +public: + void updateSinglePost(const RsGxsChannelPost& post, std::set& added_files, std::set& removed_files); +private: void initEmptyHierarchy(); std::vector mFilteredPosts; // stores the list of displayes indices due to filtering. diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.cpp index e4123dfc5..023732ed7 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.cpp @@ -784,12 +784,57 @@ void GxsChannelPostsWidgetWithModel::handleEvent_main_thread(std::shared_ptrmChannelGroupId == groupId()) { - std::set added_files,removed_files; - mChannelPostsModel->update_single_post(e->mChannelMsgId,added_files,removed_files); - mChannelFilesModel->update_files(added_files,removed_files); + RsThread::async([this,e]() + { + // 1 - get message data from p3GxsChannels. No need for pointers here, because we send only a single post to postToObject() + // At this point we dont know what kind of msg id we have. It can be a vote, a comment or an actual message. - updateDisplay(true,false); + std::vector posts; + std::vector comments; + std::vector votes; + + const auto& msg_id(e->mChannelMsgId); + const auto& grp_id(e->mChannelGroupId); + + if(!rsGxsChannels->getChannelContent(grp_id, { msg_id }, posts,comments,votes) || posts.size() != 1) + { + RsErr() << " failed to retrieve channel message data for channel/msg " << grp_id << "/" << msg_id; + return; + } + + // Need to call this in order to get the actual comment count. The previous call only retrieves the message, since we supplied the message ID. + // another way to go would be to save the comment ids of the existing message and re-insert them before calling getChannelContent. + + if(!rsGxsChannels->getChannelComments(grp_id,{ msg_id },comments)) + { + RsErr() << " failed to retrieve message comment data for channel/msg " << grp_id << "/" << msg_id ; + return; + } + + // Normally, there's a single post in the "post" array. The function below takes a full array of posts however. + + RsGxsChannelPostsModel::computeCommentCounts(posts,comments); + + // 2 - update the model in the UI thread. + + RsQThreadUtils::postToObject( [&post=posts[0],this]() + { + std::set added_files,removed_files; + + mChannelPostsModel->updateSinglePost(post,added_files,removed_files); + + std::set added_filesi,removed_filesi; + + for(auto f:added_files) added_filesi.insert(ChannelPostFileInfo(f,post.mMeta.mPublishTs)); + for(auto f:removed_files) removed_filesi.insert(ChannelPostFileInfo(f,post.mMeta.mPublishTs)); + + mChannelFilesModel->update_files(added_filesi,removed_filesi); + + updateDisplay(true,false); + + },this); + }); } } break;