mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-27 00:19:25 -05:00
finished the system to perform lighter updates of channels
This commit is contained in:
parent
a37ee4673f
commit
aba0ffa581
@ -463,7 +463,49 @@ void RsGxsChannelPostFilesModel::setFiles(const std::list<ChannelPostFileInfo> &
|
|||||||
postMods();
|
postMods();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RsGxsChannelPostFilesModel::update_files(const std::set<RsGxsFile>& added_files,const std::set<RsGxsFile>& removed_files)
|
void RsGxsChannelPostFilesModel::update_files(std::set<ChannelPostFileInfo>& added_files,std::set<ChannelPostFileInfo>& 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<mFiles.size();++i)
|
||||||
|
if(mFiles[i].mHash == f.mHash)
|
||||||
|
{
|
||||||
|
mFiles[i] = mFiles.back();
|
||||||
|
mFiles.pop_back();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 3 - add other files. We do not check that they are duplicates, because the list of files includes duplicates.
|
||||||
|
|
||||||
|
for(const auto& f:added_files )
|
||||||
|
{
|
||||||
|
mFilteredFiles.push_back(mFiles.size());
|
||||||
|
mFiles.push_back(f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ struct ChannelPostFileInfo: public RsGxsFile
|
|||||||
|
|
||||||
ChannelPostFileInfo() : mPublishTime(0) {}
|
ChannelPostFileInfo() : mPublishTime(0) {}
|
||||||
|
|
||||||
rstime_t mPublishTime;
|
rstime_t mPublishTime; // related post publish time
|
||||||
};
|
};
|
||||||
|
|
||||||
// This class is the item model used by Qt to display the information
|
// This class is the item model used by Qt to display the information
|
||||||
@ -84,7 +84,7 @@ public:
|
|||||||
void setFilter(const QStringList &strings, uint32_t &count) ;
|
void setFilter(const QStringList &strings, uint32_t &count) ;
|
||||||
|
|
||||||
// This method adds/removes the given lists of files. Useful when a single post is updated
|
// This method adds/removes the given lists of files. Useful when a single post is updated
|
||||||
void update_files(const std::set<RsGxsFile>& added_files,const std::set<RsGxsFile>& removed_files);
|
void update_files(std::set<ChannelPostFileInfo> &added_files, std::set<ChannelPostFileInfo> &removed_files);
|
||||||
|
|
||||||
#ifdef TODO
|
#ifdef TODO
|
||||||
QModelIndex getIndexOfFile(const RsFileHash& hash) const;
|
QModelIndex getIndexOfFile(const RsFileHash& hash) const;
|
||||||
|
@ -64,7 +64,7 @@ void RsGxsChannelPostsModel::setMode(TreeMode mode)
|
|||||||
triggerViewUpdate();
|
triggerViewUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateCommentCounts( std::vector<RsGxsChannelPost>& posts, std::vector<RsGxsComment>& comments)
|
void RsGxsChannelPostsModel::computeCommentCounts( std::vector<RsGxsChannelPost>& posts, std::vector<RsGxsComment>& comments)
|
||||||
{
|
{
|
||||||
// Store posts IDs in a std::map to avoid a quadratic cost
|
// 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;
|
return p1.mMeta.mPublishTs > p2.mMeta.mPublishTs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RsGxsChannelPostsModel::setSinglePost(const RsGxsChannelGroup& group, const RsGxsChannelPost& post)
|
void RsGxsChannelPostsModel::updateSinglePost(const RsGxsChannelPost& post,std::set<RsGxsFile>& added_files,std::set<RsGxsFile>& removed_files)
|
||||||
{
|
{
|
||||||
if(mChannelGroup.mMeta.mGroupId != group.mMeta.mGroupId)
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
return;
|
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)
|
for(uint32_t j=0;j<mPosts.size();++j)
|
||||||
if(post.mMeta.mMsgId == p.mMeta.mMsgId || post.mMeta.mOrigMsgId == p.mMeta.mMsgId)
|
if(new_post_meta.mMsgId == mPosts[j].mMeta.mMsgId) // same post updated
|
||||||
{
|
{
|
||||||
p = post;
|
added_files.insert(post.mFiles.begin(),post.mFiles.end());
|
||||||
found = true;
|
removed_files.insert(mPosts[j].mFiles.begin(),mPosts[j].mFiles.end());
|
||||||
|
|
||||||
|
mPosts[j] = post;
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
RsDbg() << " post is an updated existing post." ;
|
||||||
|
#endif
|
||||||
|
found=true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
else if( (new_post_meta.mOrigMsgId == mPosts[j].mMeta.mOrigMsgId || new_post_meta.mOrigMsgId == mPosts[j].mMeta.mMsgId)
|
||||||
|
&& mPosts[j].mMeta.mPublishTs < new_post_meta.mPublishTs) // new post version
|
||||||
|
{
|
||||||
|
added_files.insert(post.mFiles.begin(),post.mFiles.end());
|
||||||
|
removed_files.insert(mPosts[j].mFiles.begin(),mPosts[j].mFiles.end());
|
||||||
|
|
||||||
|
auto old_post_id = mPosts[j].mMeta.mMsgId;
|
||||||
|
mPosts[j] = post;
|
||||||
|
mPosts[j].mOlderVersions.insert(old_post_id);
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
RsDbg() << " post is an new version of an existing post." ;
|
||||||
|
#endif
|
||||||
|
found=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if(!found)
|
if(!found)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
RsDbg() << " post is an new post.";
|
||||||
|
#endif
|
||||||
|
added_files.insert(post.mFiles.begin(),post.mFiles.end());
|
||||||
mPosts.push_back(post);
|
mPosts.push_back(post);
|
||||||
|
|
||||||
std::sort(mPosts.begin(),mPosts.end());
|
std::sort(mPosts.begin(),mPosts.end());
|
||||||
|
|
||||||
mFilteredPosts.clear();
|
// We don't do that, because otherwise the filtered posts will be changed dynamically when browsing, which is bad.
|
||||||
|
//
|
||||||
for(uint32_t i=0;i<mPosts.size();++i)
|
// mFilteredPosts.clear();
|
||||||
mFilteredPosts.push_back(i);
|
// for(uint32_t i=0;i<mPosts.size();++i)
|
||||||
|
// mFilteredPosts.push_back(i);
|
||||||
#ifdef DEBUG_CHANNEL_MODEL
|
|
||||||
// debug_dump();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (rowCount()>0)
|
|
||||||
{
|
|
||||||
beginInsertRows(QModelIndex(),0,rowCount()-1);
|
|
||||||
endInsertRows();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
postMods();
|
triggerViewUpdate();
|
||||||
|
|
||||||
|
emit layoutChanged();
|
||||||
emit channelPostsLoaded();
|
emit channelPostsLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RsGxsChannelPostsModel::setPosts(const RsGxsChannelGroup& group, std::vector<RsGxsChannelPost>& posts)
|
void RsGxsChannelPostsModel::setPosts(const RsGxsChannelGroup& group, std::vector<RsGxsChannelPost>& posts)
|
||||||
{
|
{
|
||||||
preMods();
|
preMods();
|
||||||
@ -533,96 +559,7 @@ void RsGxsChannelPostsModel::setPosts(const RsGxsChannelGroup& group, std::vecto
|
|||||||
emit channelPostsLoaded();
|
emit channelPostsLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RsGxsChannelPostsModel::update_single_post(const RsGxsMessageId& msg_id,std::set<RsGxsFile>& added_files,std::set<RsGxsFile>& 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<RsGxsChannelPost> posts;
|
|
||||||
std::vector<RsGxsComment> comments;
|
|
||||||
std::vector<RsGxsVote> 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.size();++i)
|
|
||||||
{
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
// linear search. Not good at all, but normally this is for a single post.
|
|
||||||
|
|
||||||
const auto& new_post_meta(posts[i].mMeta);
|
|
||||||
|
|
||||||
for(uint32_t j=0;j<mPosts.size();++j)
|
|
||||||
if(new_post_meta.mMsgId == mPosts[j].mMeta.mMsgId) // same post updated
|
|
||||||
{
|
|
||||||
added_files.insert(posts[i].mFiles.begin(),posts[i].mFiles.end());
|
|
||||||
removed_files.insert(mPosts[j].mFiles.begin(),mPosts[j].mFiles.end());
|
|
||||||
|
|
||||||
mPosts[j] = posts[i];
|
|
||||||
#ifdef DEBUG_CHANNEL_MODEL
|
|
||||||
RsDbg() << " post is an updated existing post." ;
|
|
||||||
#endif
|
|
||||||
found=true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if( (new_post_meta.mOrigMsgId == mPosts[j].mMeta.mOrigMsgId || new_post_meta.mOrigMsgId == mPosts[j].mMeta.mMsgId)
|
|
||||||
&& mPosts[j].mMeta.mPublishTs < new_post_meta.mPublishTs) // new post version
|
|
||||||
{
|
|
||||||
added_files.insert(posts[i].mFiles.begin(),posts[i].mFiles.end());
|
|
||||||
removed_files.insert(mPosts[j].mFiles.begin(),mPosts[j].mFiles.end());
|
|
||||||
|
|
||||||
posts[i].mOlderVersions.insert(new_post_meta.mMsgId);
|
|
||||||
mPosts[j] = posts[i];
|
|
||||||
#ifdef DEBUG_CHANNEL_MODEL
|
|
||||||
RsDbg() << " post is an new version of an existing post." ;
|
|
||||||
#endif
|
|
||||||
found=true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!found)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG_CHANNEL_MODEL
|
|
||||||
RsDbg() << " post is an new post.";
|
|
||||||
#endif
|
|
||||||
added_files.insert(posts[i].mFiles.begin(),posts[i].mFiles.end());
|
|
||||||
mPosts.push_back(posts[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
triggerViewUpdate();
|
|
||||||
|
|
||||||
},this);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void RsGxsChannelPostsModel::update_posts(const RsGxsGroupId& group_id)
|
void RsGxsChannelPostsModel::update_posts(const RsGxsGroupId& group_id)
|
||||||
{
|
{
|
||||||
@ -666,7 +603,7 @@ void RsGxsChannelPostsModel::update_posts(const RsGxsGroupId& group_id)
|
|||||||
// This shouldn't be needed normally. We need it until a background process computes the number of comments per
|
// This shouldn't be needed normally. We need it until a background process computes the number of comments per
|
||||||
// post and stores it in the service string. Since we request all data, this process isn't costing much anyway.
|
// post and stores it in the service string. Since we request all data, this process isn't costing much anyway.
|
||||||
|
|
||||||
updateCommentCounts(*posts,*comments);
|
computeCommentCounts(*posts,*comments);
|
||||||
|
|
||||||
// 2 - update the model in the UI thread.
|
// 2 - update the model in the UI thread.
|
||||||
|
|
||||||
|
@ -101,6 +101,7 @@ public:
|
|||||||
SORT_MODE_CHILDREN_PUBLISH_TS = 0x01,
|
SORT_MODE_CHILDREN_PUBLISH_TS = 0x01,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
static void computeCommentCounts( std::vector<RsGxsChannelPost>& posts, std::vector<RsGxsComment>& comments);
|
||||||
|
|
||||||
QModelIndex root() const{ return createIndex(0,0,(void*)NULL) ;}
|
QModelIndex root() const{ return createIndex(0,0,(void*)NULL) ;}
|
||||||
QModelIndex getIndexOfMessage(const RsGxsMessageId& mid) const;
|
QModelIndex getIndexOfMessage(const RsGxsMessageId& mid) const;
|
||||||
@ -214,8 +215,6 @@ private:
|
|||||||
static void computeReputationLevel(uint32_t forum_sign_flags, RsGxsChannelPost& entry);
|
static void computeReputationLevel(uint32_t forum_sign_flags, RsGxsChannelPost& entry);
|
||||||
|
|
||||||
void update_posts(const RsGxsGroupId& group_id);
|
void update_posts(const RsGxsGroupId& group_id);
|
||||||
public:
|
|
||||||
void update_single_post(const RsGxsMessageId& msgId, std::set<RsGxsFile> &added_files, std::set<RsGxsFile> &removed_files);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -235,7 +234,9 @@ private:
|
|||||||
//void computeMessagesHierarchy(const RsGxsChannelGroup& forum_group, const std::vector<RsMsgMetaData> &msgs_array, std::vector<ChannelPostsModelPostEntry> &posts, std::map<RsGxsMessageId, std::vector<std::pair<time_t, RsGxsMessageId> > > &mPostVersions);
|
//void computeMessagesHierarchy(const RsGxsChannelGroup& forum_group, const std::vector<RsMsgMetaData> &msgs_array, std::vector<ChannelPostsModelPostEntry> &posts, std::map<RsGxsMessageId, std::vector<std::pair<time_t, RsGxsMessageId> > > &mPostVersions);
|
||||||
void createPostsArray(std::vector<RsGxsChannelPost> &posts);
|
void createPostsArray(std::vector<RsGxsChannelPost> &posts);
|
||||||
void setPosts(const RsGxsChannelGroup& group, std::vector<RsGxsChannelPost> &posts);
|
void setPosts(const RsGxsChannelGroup& group, std::vector<RsGxsChannelPost> &posts);
|
||||||
void setSinglePost(const RsGxsChannelGroup& group, const RsGxsChannelPost& post);
|
public:
|
||||||
|
void updateSinglePost(const RsGxsChannelPost& post, std::set<RsGxsFile>& added_files, std::set<RsGxsFile>& removed_files);
|
||||||
|
private:
|
||||||
void initEmptyHierarchy();
|
void initEmptyHierarchy();
|
||||||
|
|
||||||
std::vector<int> mFilteredPosts; // stores the list of displayes indices due to filtering.
|
std::vector<int> mFilteredPosts; // stores the list of displayes indices due to filtering.
|
||||||
|
@ -783,13 +783,58 @@ void GxsChannelPostsWidgetWithModel::handleEvent_main_thread(std::shared_ptr<con
|
|||||||
case RsChannelEventCode::NEW_MESSAGE:
|
case RsChannelEventCode::NEW_MESSAGE:
|
||||||
{
|
{
|
||||||
if(e->mChannelGroupId == groupId())
|
if(e->mChannelGroupId == groupId())
|
||||||
|
{
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
std::vector<RsGxsChannelPost> posts;
|
||||||
|
std::vector<RsGxsComment> comments;
|
||||||
|
std::vector<RsGxsVote> 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<RsGxsFile> added_files,removed_files;
|
std::set<RsGxsFile> added_files,removed_files;
|
||||||
|
|
||||||
mChannelPostsModel->update_single_post(e->mChannelMsgId,added_files,removed_files);
|
mChannelPostsModel->updateSinglePost(post,added_files,removed_files);
|
||||||
mChannelFilesModel->update_files(added_files,removed_files);
|
|
||||||
|
std::set<ChannelPostFileInfo> 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);
|
updateDisplay(true,false);
|
||||||
|
|
||||||
|
},this);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user