diff --git a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.cpp b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.cpp index 2b56e9ba6..1d37e48b1 100644 --- a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.cpp +++ b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.cpp @@ -48,56 +48,88 @@ GxsForumMsgItem::GxsForumMsgItem(FeedHolder *feedHolder, uint32_t feedId, const mMessage.mMeta.mMsgId = messageId; // useful for uniqueIdentifier() before the post is actually loaded mMessage.mMeta.mGroupId = groupId; + mLoadingStatus = NO_DATA; + mLoadingGroup = false; mLoadingMessage = false; mLoadingSetAsRead = false; - mLoadingParentMessage = false; setup(); - - requestGroup(); - requestMessage(); } -GxsForumMsgItem::GxsForumMsgItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsForumGroup &group, const RsGxsForumMsg &post, bool isHome, bool autoUpdate) : - GxsFeedItem(feedHolder, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsGxsForums, autoUpdate) +// GxsForumMsgItem::GxsForumMsgItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsForumGroup &group, const RsGxsForumMsg &post, bool isHome, bool autoUpdate) : +// GxsFeedItem(feedHolder, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsGxsForums, autoUpdate) +// { +// #ifdef DEBUG_ITEM +// std::cerr << "GxsForumMsgItem::GxsForumMsgItem() Direct Load"; +// std::cerr << std::endl; +// #endif +// +// setup(); +// +// setGroup(group, false); +// setMessage(post); +// } + +// GxsForumMsgItem::GxsForumMsgItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsForumMsg &post, bool isHome, bool autoUpdate) : +// GxsFeedItem(feedHolder, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsGxsForums, autoUpdate) +// { +// #ifdef DEBUG_ITEM +// std::cerr << "GxsForumMsgItem::GxsForumMsgItem() Direct Load"; +// std::cerr << std::endl; +// #endif +// +// setup(); +// +// requestGroup(); +// setMessage(post); +// } + +void GxsForumMsgItem::paintEvent(QPaintEvent *e) { -#ifdef DEBUG_ITEM - std::cerr << "GxsForumMsgItem::GxsForumMsgItem() Direct Load"; - std::cerr << std::endl; -#endif + /* This method employs a trick to trigger a deferred loading. The post and group is requested only + * when actually displayed on the screen. */ - setup(); + if(mLoadingStatus != FILLED && !mGroup.mMeta.mGroupId.isNull() && !mMessage.mMeta.mMsgId.isNull()) + mLoadingStatus = HAS_DATA; - setGroup(group, false); - setMessage(post); -} + if(mGroup.mMeta.mGroupId.isNull() && !mLoadingGroup) + requestGroup(); -GxsForumMsgItem::GxsForumMsgItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsForumMsg &post, bool isHome, bool autoUpdate) : - GxsFeedItem(feedHolder, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsGxsForums, autoUpdate) -{ -#ifdef DEBUG_ITEM - std::cerr << "GxsForumMsgItem::GxsForumMsgItem() Direct Load"; - std::cerr << std::endl; -#endif + if(mMessage.mMeta.mMsgId.isNull() && !mLoadingMessage) + requestMessage(); - setup(); + switch(mLoadingStatus) + { + case FILLED: + case NO_DATA: + default: + break; - requestGroup(); - setMessage(post); + case HAS_DATA: + fillGroup(); + fillMessage(); + + if(!mParentMessage.mMeta.mMsgId.isNull()) + fillParentMessage(); + + mLoadingStatus = FILLED; + break; + } + + GxsFeedItem::paintEvent(e) ; } GxsForumMsgItem::~GxsForumMsgItem() { auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(GROUP_ITEM_LOADING_TIMEOUT_ms); - while( (mLoadingGroup || mLoadingMessage || mLoadingSetAsRead || mLoadingParentMessage) + while( (mLoadingGroup || mLoadingMessage || mLoadingSetAsRead) && std::chrono::steady_clock::now() < timeout) { RsDbg() << __PRETTY_FUNCTION__ << " is Waiting for " << (mLoadingGroup ? "Group " : "") << (mLoadingMessage ? "Message " : "") - << (mLoadingParentMessage ? "Parent message " : "") << (mLoadingSetAsRead ? "Set as read" : "") << "loading." << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(100)); @@ -113,7 +145,6 @@ void GxsForumMsgItem::setup() setAttribute(Qt::WA_DeleteOnClose, true); - mInFill = false; mCloseOnRead = false; /* clear ui */ @@ -144,41 +175,6 @@ void GxsForumMsgItem::setup() ui->parentFrame->hide(); } -bool GxsForumMsgItem::setGroup(const RsGxsForumGroup &group, bool doFill) -{ - if (groupId() != group.mMeta.mGroupId) { - std::cerr << "GxsForumMsgItem::setGroup() - Wrong id, cannot set post"; - std::cerr << std::endl; - return false; - } - - mGroup = group; - - if (doFill) - fillGroup(); - - return true; -} - -bool GxsForumMsgItem::setMessage(const RsGxsForumMsg &msg, bool doFill) -{ - if (groupId() != msg.mMeta.mGroupId || messageId() != msg.mMeta.mMsgId) { - std::cerr << "GxsForumMsgItem::setPost() - Wrong id, cannot set post"; - std::cerr << std::endl; - return false; - } - - mMessage = msg; - - if(! mMessage.mMeta.mParentId.isNull()) - loadParentMessage(mMessage.mMeta.mParentId); - - if(doFill) - fillMessage(); - - return true; -} - QString GxsForumMsgItem::groupName() { return QString::fromUtf8(mGroup.mMeta.mGroupName.c_str()); @@ -221,7 +217,7 @@ void GxsForumMsgItem::loadGroup() * thread, for example to update the data model with new information * after a blocking call to RetroShare API complete */ - setGroup(group); + mGroup = group; mLoadingGroup = false; }, this ); @@ -244,93 +240,50 @@ void GxsForumMsgItem::loadMessage() std::cerr << "Retrieving post data for post " << mThreadId << std::endl; #endif - std::vector msgs; - const std::list forumIds = { groupId() }; + auto getMessageData = [](const RsGxsGroupId& gid,const RsGxsMessageId& msg_id,RsGxsForumMsg& msg) -> bool + { + std::vector msgs; - if(!rsGxsForums->getForumContent(groupId(),std::set( { messageId() } ),msgs)) - { - std::cerr << "GxsForumMsgItem::loadMessage() ERROR getting data"; - std::cerr << std::endl; + if(!rsGxsForums->getForumContent(gid,std::set( { msg_id } ),msgs)) + return false; + + if (msgs.size() != 1) + return false; + + msg = msgs[0]; + + return true; + }; + + RsGxsForumMsg msg,parent_msg; + + if(!getMessageData(groupId(),messageId(),msg)) + { + std::cerr << "GxsForumMsgItem::loadMessage() ERROR getting message data"; mLoadingMessage = false; return; - } + } + // now load the parent message. If not found, it's not a problem. - if (msgs.size() != 1) - { - std::cerr << "GxsForumMsgItem::loadMessage() Wrong number of Items"; - std::cerr << std::endl; - mLoadingMessage = false; - return; - } - RsGxsForumMsg msg(msgs[0]); + if(!msg.mMeta.mParentId.isNull() && !getMessageData(groupId(),msg.mMeta.mParentId,parent_msg)) + std::cerr << "GxsForumMsgItem::loadMessage() ERROR getting parent message data. Maybe the parent msg is not available."; - RsQThreadUtils::postToObject( [msg,this]() + RsQThreadUtils::postToObject( [msg,parent_msg,this]() { /* Here it goes any code you want to be executed on the Qt Gui * thread, for example to update the data model with new information * after a blocking call to RetroShare API complete */ - setMessage(msg); + mMessage = msg; + mParentMessage = parent_msg; mLoadingMessage = false; }, this ); }); } -void GxsForumMsgItem::loadParentMessage(const RsGxsMessageId& parent_msg) -{ -#ifdef DEBUG_ITEM - std::cerr << "GxsForumMsgItem::loadParentMessage()"; - std::cerr << std::endl; -#endif - mLoadingParentMessage = true; - - RsThread::async([parent_msg,this]() - { - // 1 - get group data - -#ifdef DEBUG_FORUMS - std::cerr << "Retrieving post data for post " << mThreadId << std::endl; -#endif - - std::vector msgs; - const std::list forumIds = { groupId() }; - - if(!rsGxsForums->getForumContent(groupId(),std::set( { parent_msg } ),msgs)) - { - std::cerr << "GxsForumMsgItem::loadMessage() ERROR getting data"; - std::cerr << std::endl; - mLoadingParentMessage = false; - return; - } - - if (msgs.size() != 1) - { - std::cerr << "GxsForumMsgItem::loadMessage() Wrong number of Items"; - std::cerr << std::endl; - mLoadingParentMessage = false; - return; - } - RsGxsForumMsg msg(msgs[0]); - - RsQThreadUtils::postToObject( [msg,this]() - { - /* Here it goes any code you want to be executed on the Qt Gui - * thread, for example to update the data model with new information - * after a blocking call to RetroShare API complete */ - - mParentMessage = msg; - fillParentMessage(); - - mLoadingParentMessage = false; - - }, this ); - }); -} void GxsForumMsgItem::fillParentMessage() { - mInFill = true; - ui->parentFrame->hide(); RetroShareLink linkParent = RetroShareLink::createGxsMessageLink(RetroShareLink::TYPE_FORUM, mParentMessage.mMeta.mGroupId, mParentMessage.mMeta.mMsgId, QString::fromUtf8(mParentMessage.mMeta.mMsgName.c_str())); @@ -347,8 +300,6 @@ void GxsForumMsgItem::fillParentMessage() pixmap = GxsIdDetails::makeDefaultIcon(mParentMessage.mMeta.mAuthorId,GxsIdDetails::SMALL); ui->parentAvatar->setPixmap(pixmap); - - mInFill = false; } void GxsForumMsgItem::fillMessage() { @@ -357,8 +308,6 @@ void GxsForumMsgItem::fillMessage() std::cerr << std::endl; #endif - mInFill = true; - if(!mIsHome && mCloseOnRead && !IS_MSG_NEW(mMessage.mMeta.mMsgStatus)) removeItem(); @@ -400,21 +349,15 @@ void GxsForumMsgItem::fillMessage() ui->clearButton->setEnabled(false); ui->clearButton->hide(); } - - mInFill = false; } void GxsForumMsgItem::fillGroup() { - mInFill = true; - ui->unsubscribeButton->setEnabled(IS_GROUP_SUBSCRIBED(mGroup.mMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroup.mMeta.mSubscribeFlags)) ; if (IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags)) ui->iconLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/forums.png")); else ui->iconLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/forums-default.png")); - - mInFill = false; } void GxsForumMsgItem::fillExpandFrame() @@ -508,10 +451,6 @@ void GxsForumMsgItem::unsubscribeForum() void GxsForumMsgItem::setAsRead(bool doUpdate) { - if (mInFill) { - return; - } - mCloseOnRead = false; mLoadingSetAsRead = true; diff --git a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.h b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.h index ec933d96e..8d882785e 100644 --- a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.h +++ b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.h @@ -36,22 +36,18 @@ class GxsForumMsgItem : public GxsFeedItem public: GxsForumMsgItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate); - GxsForumMsgItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsForumGroup &group, const RsGxsForumMsg &post, bool isHome, bool autoUpdate); - GxsForumMsgItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsForumMsg &post, bool isHome, bool autoUpdate); - virtual ~GxsForumMsgItem(); - bool setGroup(const RsGxsForumGroup &group, bool doFill = true); - bool setMessage(const RsGxsForumMsg &msg, bool doFill = true); + //GxsForumMsgItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsForumGroup &group, const RsGxsForumMsg &post, bool isHome, bool autoUpdate); + //GxsForumMsgItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsForumMsg &post, bool isHome, bool autoUpdate); + virtual ~GxsForumMsgItem(); uint64_t uniqueIdentifier() const override { return hash_64bits("GxsForumMsgItem " + messageId().toStdString()) ; } protected: - /* FeedItem */ + virtual void paintEvent(QPaintEvent *e) override; + /* FeedItem */ virtual void doExpand(bool open) override; virtual void expandFill(bool first) override; - /* load message data */ - virtual void loadParentMessage(const RsGxsMessageId &parent_msg); - /* GxsGroupFeedItem */ virtual QString groupName() override; virtual void loadGroup() override; @@ -77,6 +73,7 @@ signals: private: void setup(); + void fillGroup(); void fillMessage(); void fillParentMessage(); @@ -85,16 +82,19 @@ private: void setAsRead(bool doUpdate); private: - bool mInFill; bool mCloseOnRead; + + LoadingStatus mLoadingStatus; + bool mLoadingMessage; - bool mLoadingParentMessage; bool mLoadingGroup; bool mLoadingSetAsRead; + bool mHasParentMessage; // set to false when we see that the msg does not have a parent. + RsGxsForumGroup mGroup; - RsGxsForumMsg mMessage; - RsGxsForumMsg mParentMessage; + RsGxsForumMsg mMessage; + RsGxsForumMsg mParentMessage; /** Qt Designer generated object */ Ui::GxsForumMsgItem *ui;