diff --git a/retroshare-gui/src/gui/NewsFeed.cpp b/retroshare-gui/src/gui/NewsFeed.cpp index c73f834fb..dc0834e71 100644 --- a/retroshare-gui/src/gui/NewsFeed.cpp +++ b/retroshare-gui/src/gui/NewsFeed.cpp @@ -299,7 +299,7 @@ void NewsFeed::handleChannelEvent(std::shared_ptr event) addFeedItem(new GxsChannelPostItem(this, NEWSFEED_CHANNELNEWLIST, pe->mChannelGroupId, pe->mChannelMsgId, false, true)); break; case RsChannelEventCode::NEW_COMMENT: - addFeedItem(new ChannelsCommentsItem(this, NEWSFEED_CHANNELNEWLIST, pe->mChannelGroupId, pe->mChannelMsgId, false, true)); + addFeedItem(new ChannelsCommentsItem(this, NEWSFEED_CHANNELNEWLIST, pe->mChannelGroupId, pe->mChannelMsgId,pe->mChannelThreadId, false, true)); break; case RsChannelEventCode::RECEIVED_PUBLISH_KEY: addFeedItem(new GxsChannelGroupItem(this, NEWSFEED_CHANNELPUBKEYLIST, pe->mChannelGroupId, false, true)); diff --git a/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.cpp b/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.cpp index 527ca8698..46c129ebe 100644 --- a/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.cpp +++ b/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.cpp @@ -49,54 +49,41 @@ * #define DEBUG_ITEM 1 ****/ -ChannelsCommentsItem::ChannelsCommentsItem(FeedHolder *feedHolder, uint32_t feedId, const RsGroupMetaData& group_meta, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate,const std::set& older_versions) : - GxsFeedItem(feedHolder, feedId, group_meta.mGroupId, messageId, isHome, rsGxsChannels, autoUpdate), - mGroupMeta(group_meta) -{ - mLoadingGroup = false; - mLoadingMessage = false; - mLoadingComment = false; +// ChannelsCommentsItem::ChannelsCommentsItem(FeedHolder *feedHolder, uint32_t feedId, const RsGroupMetaData& group_meta, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate,const std::set& older_versions) : +// GxsFeedItem(feedHolder, feedId, group_meta.mGroupId, messageId, isHome, rsGxsChannels, autoUpdate), +// mGroupMeta(group_meta) +// { +// mLoadingGroup = false; +// mLoadingMessage = false; +// mLoadingComment = false; +// +// mPost.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded +// mPost.mMeta.mGroupId = mGroupMeta.mGroupId; +// +// QVector v; +// //bool self = false; +// +// for(std::set::const_iterator it(older_versions.begin());it!=older_versions.end();++it) +// v.push_back(*it) ; +// +// if(older_versions.find(messageId) == older_versions.end()) +// v.push_back(messageId); +// +// setMessageVersions(v) ; +// setup(); +// +// // no call to loadGroup() here because we have it already. +// } - mPost.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded - mPost.mMeta.mGroupId = mGroupMeta.mGroupId; +ChannelsCommentsItem::ChannelsCommentsItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &commentId, const RsGxsMessageId &threadId, bool isHome, bool autoUpdate) : + GxsFeedItem(feedHolder, feedId, groupId, commentId, isHome, rsGxsChannels, autoUpdate), // this one should be in GxsFeedItem + mThreadId(threadId) +{ + mLoading= false; QVector v; - //bool self = false; - for(std::set::const_iterator it(older_versions.begin());it!=older_versions.end();++it) - v.push_back(*it) ; - - if(older_versions.find(messageId) == older_versions.end()) - v.push_back(messageId); - - setMessageVersions(v) ; setup(); - - // no call to loadGroup() here because we have it already. -} - -ChannelsCommentsItem::ChannelsCommentsItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate,const std::set& older_versions) : - GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsGxsChannels, autoUpdate) // this one should be in GxsFeedItem -{ - mLoadingGroup = false; - mLoadingMessage = false; - mLoadingComment = false; - - mPost.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded - - QVector v; - //bool self = false; - - for(std::set::const_iterator it(older_versions.begin());it!=older_versions.end();++it) - v.push_back(*it) ; - - if(older_versions.find(messageId) == older_versions.end()) - v.push_back(messageId); - - setMessageVersions(v) ; - setup(); - - loadGroup(); } void ChannelsCommentsItem::paintEvent(QPaintEvent *e) @@ -107,15 +94,8 @@ void ChannelsCommentsItem::paintEvent(QPaintEvent *e) if(!mLoaded) { mLoaded = true ; - - std::set older_versions; // not so nice. We need to use std::set everywhere - for(auto& m:messageVersions()) - older_versions.insert(m); - - fill(); - requestMessage(); - requestComment(); - } + load(); + } GxsFeedItem::paintEvent(e) ; } @@ -124,14 +104,9 @@ ChannelsCommentsItem::~ChannelsCommentsItem() { auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(300); - while( (mLoadingGroup || mLoadingMessage || mLoadingComment) - && std::chrono::steady_clock::now() < timeout) + while( mLoading && std::chrono::steady_clock::now() < timeout ) { - RsDbg() << __PRETTY_FUNCTION__ << " is Waiting for " - << (mLoadingGroup ? "Group " : "") - << (mLoadingMessage ? "Message " : "") - << (mLoadingComment ? "Comment " : "") - << "loading." << std::endl; + RsDbg() << __PRETTY_FUNCTION__ << " is Waiting for data to load " << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(100)); } @@ -203,21 +178,24 @@ void ChannelsCommentsItem::setup() ui->expandFrame->hide(); } -bool ChannelsCommentsItem::setPost(const RsGxsChannelPost &post, bool doFill) +bool ChannelsCommentsItem::setPost(const RsGxsChannelPost& post, bool doFill) { - if (groupId() != post.mMeta.mGroupId || messageId() != post.mMeta.mMsgId) { - std::cerr << "ChannelsCommentsItem::setPost() - Wrong id, cannot set post"; - std::cerr << std::endl; - return false; - } - mPost = post; - if (doFill) { + if (doFill) fill(); - } - return true; + std::cerr << "end setting post." << std::endl; + return true; +} +bool ChannelsCommentsItem::setMissingPost() +{ + std::cerr << "setting missing post." << std::endl; + + fill(true); + + std::cerr << "end setting missing post." << std::endl; + return true; } QString ChannelsCommentsItem::getTitleLabel() @@ -251,178 +229,150 @@ void ChannelsCommentsItem::loadComments() void ChannelsCommentsItem::loadGroup() { -#ifdef DEBUG_ITEM - std::cerr << "GxsChannelGroupItem::loadGroup()"; - std::cerr << std::endl; -#endif - - RsThread::async([this]() - { - // 1 - get group data - - std::vector groups; - const std::list groupIds = { groupId() }; - - if(!rsGxsChannels->getChannelsInfo(groupIds,groups)) // would be better to call channel Summaries for a single group - { - RsErr() << "GxsGxsChannelGroupItem::loadGroup() ERROR getting data" << std::endl; - return; - } - - if (groups.size() != 1) - { - std::cerr << "GxsGxsChannelGroupItem::loadGroup() Wrong number of Items"; - std::cerr << std::endl; - return; - } - RsGxsChannelGroup group(groups[0]); - mLoadingGroup = true; - - RsQThreadUtils::postToObject( [group,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 */ - - mGroupMeta = group.mMeta; - mLoadingGroup = false; - - }, this ); - }); +//#ifdef DEBUG_ITEM +// std::cerr << "GxsChannelGroupItem::loadGroup()"; +// std::cerr << std::endl; +//#endif +// if(mLoading) +// return; +// +// mLoading= true; +// +// std::cerr << "Loading group" << std::endl; +// RsThread::async([this]() +// { +// // 1 - get group data +// +// std::vector groups; +// const std::list groupIds = { groupId() }; +// +// if(!rsGxsChannels->getChannelsInfo(groupIds,groups)) // would be better to call channel Summaries for a single group +// { +// RsErr() << "GxsGxsChannelGroupItem::loadGroup() ERROR getting data" << std::endl; +// return; +// } +// +// if (groups.size() != 1) +// { +// std::cerr << "GxsGxsChannelGroupItem::loadGroup() Wrong number of Items"; +// std::cerr << std::endl; +// return; +// } +// RsGxsChannelGroup group(groups[0]); +// +// RsQThreadUtils::postToObject( [group,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 */ +// +// mGroupMeta = group.mMeta; +// mLoading= false; +// +// std::cerr << "End loading group" << std::endl; +// }, this ); +// }); } -void ChannelsCommentsItem::loadMessage() +void ChannelsCommentsItem::load() { + // This function loads everything that's needed: + // - the comment text + // - the comment parent message + #ifdef DEBUG_ITEM std::cerr << "ChannelsCommentsItem::loadMessage()"; std::cerr << std::endl; #endif - RsThread::async([this]() + if(mLoading) + return; + + mLoading= true; + std::cerr << "Loading message " << mPost.mMeta.mMsgId << std::endl; + + RsThread::async([this]() { - // 1 - get group data + // 1 - get group meta data + + std::vector groups; + const std::list groupIds = { groupId() }; + + if(!rsGxsChannels->getChannelsInfo(groupIds,groups)) // would be better to call channel Summaries for a single group + { + RsErr() << "GxsGxsChannelGroupItem::loadGroup() ERROR getting data" << std::endl; + return; + } + + if (groups.size() != 1) + { + std::cerr << "GxsGxsChannelGroupItem::loadGroup() Wrong number of Items"; + std::cerr << std::endl; + return; + } + RsGxsChannelGroup group(groups[0]); + + // 2 - get message and comment data std::vector posts; std::vector comments; std::vector votes; - if(! rsGxsChannels->getChannelContent( groupId(), std::set( { messageId() } ),posts,comments,votes)) + if(! rsGxsChannels->getChannelContent( groupId(), std::set( { messageId(),mThreadId } ),posts,comments,votes)) { RsErr() << "GxsGxsChannelGroupItem::loadGroup() ERROR getting data" << std::endl; return; } - if (posts.size() == 1) - { -#ifdef DEBUG_ITEM - std::cerr << (void*)this << ": Obtained post, with msgId = " << posts[0].mMeta.mMsgId << std::endl; -#endif - RsGxsChannelPost post(posts[0]); // no reference to temporary here, because we pass this to a thread - mLoadingMessage = true; + // now that everything is in place, update the UI - RsQThreadUtils::postToObject( [post,this]() { setPost(post); mLoadingMessage=false; }, this ); - } - else if(comments.size() == 1) - { - RsGxsComment cmt(comments[0]); -#ifdef DEBUG_ITEM - std::cerr << (void*)this << ": Obtained comment, setting messageId to threadID = " << cmt.mMeta.mThreadId << std::endl; -#endif - mLoadingComment = true; + RsQThreadUtils::postToObject( [group,posts,comments,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 */ - RsQThreadUtils::postToObject( [cmt,this]() - { - uint32_t autorized_lines = (int)floor( (ui->avatarLabel->height() - ui->button_HL->sizeHint().height()) - / QFontMetricsF(ui->subjectLabel->font()).height()); + mGroupMeta = group.mMeta; - ui->commLabel->setText(RsHtml().formatText(NULL, RsStringUtil::CopyLines(QString::fromUtf8(cmt.mComment.c_str()), autorized_lines), RSHTML_FORMATTEXT_EMBED_LINKS)); + if(comments.size()==1) + { + RsGxsComment cmt(comments[0]); - ui->nameLabel->setId(cmt.mMeta.mAuthorId); - ui->datetimeLabel->setText(DateTime::formatLongDateTime(cmt.mMeta.mPublishTs)); + std::cerr << "setting comment." << std::endl; + uint32_t autorized_lines = (int)floor( (ui->avatarLabel->height() - ui->button_HL->sizeHint().height()) + / QFontMetricsF(ui->subjectLabel->font()).height()); - RsIdentityDetails idDetails ; - rsIdentity->getIdDetails(cmt.mMeta.mAuthorId,idDetails); - QPixmap pixmap ; + ui->commLabel->setText(RsHtml().formatText(NULL, RsStringUtil::CopyLines(QString::fromUtf8(cmt.mComment.c_str()), autorized_lines), RSHTML_FORMATTEXT_EMBED_LINKS)); + ui->nameLabel->setId(cmt.mMeta.mAuthorId); + ui->datetimeLabel->setText(DateTime::formatLongDateTime(cmt.mMeta.mPublishTs)); - if(idDetails.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idDetails.mAvatar.mData, idDetails.mAvatar.mSize, pixmap,GxsIdDetails::SMALL)) - pixmap = GxsIdDetails::makeDefaultIcon(cmt.mMeta.mAuthorId,GxsIdDetails::LARGE); - ui->avatarLabel->setPixmap(pixmap); + RsIdentityDetails idDetails ; + rsIdentity->getIdDetails(cmt.mMeta.mAuthorId,idDetails); + QPixmap pixmap ; - //Change this item to be uploaded with thread element. - setMessageId(cmt.mMeta.mThreadId); - mLoadingComment=false; - requestMessage(); + if(idDetails.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idDetails.mAvatar.mData, idDetails.mAvatar.mSize, pixmap,GxsIdDetails::SMALL)) + pixmap = GxsIdDetails::makeDefaultIcon(cmt.mMeta.mAuthorId,GxsIdDetails::LARGE); + ui->avatarLabel->setPixmap(pixmap); - }, this ); + //Change this item to be uploaded with thread element. This is really bad practice. - } - else - { -#ifdef DEBUG_ITEM - std::cerr << "ChannelsCommentsItem::loadMessage() Wrong number of Items. Remove It."; - std::cerr << std::endl; -#endif + mLoading=false; + } + else + removeItem(); - RsQThreadUtils::postToObject( [this]() { removeItem(); }, this ); - } - }); - - emit sizeChanged(this); + if (posts.size() == 1) + setPost(posts[0]); + else + setMissingPost(); + + std::cerr << "End loading channel post comment data" << std::endl; + emit sizeChanged(this); + + }, this ); + }); } -void ChannelsCommentsItem::loadComment() +void ChannelsCommentsItem::fill(bool missing_post) { -#ifdef DOES_NOTHING - -#ifdef DEBUG_ITEM - std::cerr << "ChannelsCommentsItem::loadComment()"; - std::cerr << std::endl; -#endif - - RsThread::async([this]() - { - // 1 - get group data - - std::set msgIds; - - for(auto MsgId: messageVersions()) - msgIds.insert(MsgId); - - std::vector posts; - std::vector comments; - - if(! rsGxsChannels->getChannelComments( groupId(),msgIds,comments)) - { - RsErr() << "GxsGxsChannelGroupItem::loadGroup() ERROR getting data" << std::endl; - return; - } - - int comNb = comments.size(); - - mLoadingComment=true; - - RsQThreadUtils::postToObject( [comNb]() - { - QString sComButText = tr("Comment"); - if (comNb == 1) - sComButText = sComButText.append("(1)"); - else if(comNb > 1) - sComButText = tr("Comments ").append("(%1)").arg(comNb); - - //ui->commentButton->setText(sComButText); - - }, this ); - }); -#endif -} - -void ChannelsCommentsItem::fill() -{ - /* fill in */ - -// if (isLoading()) { - // /* Wait for all requests */ - //return; -// } - #ifdef DEBUG_ITEM std::cerr << "ChannelsCommentsItem::fill()"; std::cerr << std::endl; @@ -430,9 +380,6 @@ void ChannelsCommentsItem::fill() mInFill = true; - //QString title; - //float f = QFontMetricsF(font()).height()/14.0 ; - if (!mIsHome) { if (mCloseOnRead && !IS_MSG_NEW(mPost.mMeta.mMsgStatus)) { @@ -443,19 +390,14 @@ void ChannelsCommentsItem::fill() //title += link.toHtml(); //ui->titleLabel->setText(title); - RetroShareLink msgLink = RetroShareLink::createGxsMessageLink(RetroShareLink::TYPE_CHANNEL, mPost.mMeta.mGroupId, mPost.mMeta.mMsgId, messageName()); - ui->subjectLabel->setText(msgLink.toHtml()); + RetroShareLink msgLink = RetroShareLink::createGxsMessageLink(RetroShareLink::TYPE_CHANNEL, mPost.mMeta.mGroupId, mPost.mMeta.mMsgId, messageName()); + + if(missing_post) + ui->subjectLabel->setText("[" + QObject::tr("Missing channel post")+"]"); + else + ui->subjectLabel->setText(msgLink.toHtml()); - if (IS_GROUP_SUBSCRIBED(mGroupMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroupMeta.mSubscribeFlags)) - { - //ui->unsubscribeButton->setEnabled(true); - } - else - { - //ui->unsubscribeButton->setEnabled(false); - } ui->readButton->hide(); - //ui->titleLabel->hide(); if (IS_MSG_NEW(mPost.mMeta.mMsgStatus)) { mCloseOnRead = true; @@ -463,19 +405,10 @@ void ChannelsCommentsItem::fill() } else { - /* subject */ - //ui->titleLabel->setText(QString::fromUtf8(mPost.mMeta.mMsgName.c_str())); - - //uint32_t autorized_lines = (int)floor( (ui->avatarLabel->height() - ui->button_HL->sizeHint().height()) - // / QFontMetricsF(ui->subjectLabel->font()).height()); - - // fill first 4 lines of message. (csoler) Disabled the replacement of smileys and links, because the cost is too crazy - //ui->subjectLabel->setText(RsHtml().formatText(NULL, RsStringUtil::CopyLines(QString::fromUtf8(mPost.mMsg.c_str()), autorized_lines), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); - - ui->subjectLabel->setText(RsStringUtil::CopyLines(QString::fromUtf8(mPost.mMsg.c_str()), 2)) ; - - //QString score = QString::number(post.mTopScore); - // scoreLabel->setText(score); + if(missing_post) + ui->subjectLabel->setText("[" + QObject::tr("Missing channel post")+"]"); + else + ui->subjectLabel->setText(RsStringUtil::CopyLines(QString::fromUtf8(mPost.mMsg.c_str()), 2)) ; /* disable buttons: deletion facility not enabled with cache services yet */ ui->clearButton->setEnabled(false); @@ -498,50 +431,9 @@ void ChannelsCommentsItem::fill() mCloseOnRead = false; } - // differences between Feed or Top of Comment. - if (mFeedHolder) - { - //ui->commentButton->show(); - - // Not yet functional - /*if (mPost.mCommentCount) - { - QString commentText = QString::number(mPost.mCommentCount); - commentText += " "; - commentText += tr("Comments"); - ui->commentButton->setText(commentText); - } - else - { - ui->commentButton->setText(tr("Comment")); - }*/ - - } - else - { - //ui->commentButton->hide(); - } - - // disable voting buttons - if they have already voted. - /*if (post.mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK) - { - voteUpButton->setEnabled(false); - voteDownButton->setEnabled(false); - }*/ - - if (wasExpanded() || ui->expandFrame->isVisible()) { - fillExpandFrame(); - } - mInFill = false; } -void ChannelsCommentsItem::fillExpandFrame() -{ - //ui->msgLabel->setText(RsHtml().formatText(NULL, QString::fromUtf8(mPost.mMsg.c_str()), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); - -} - QString ChannelsCommentsItem::messageName() { return QString::fromUtf8(mPost.mMeta.mMsgName.c_str()); @@ -605,10 +497,6 @@ void ChannelsCommentsItem::doExpand(bool open) void ChannelsCommentsItem::expandFill(bool first) { GxsFeedItem::expandFill(first); - - if (first) { - fillExpandFrame(); - } } void ChannelsCommentsItem::toggle() diff --git a/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.h b/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.h index c790e3107..c245cbca7 100644 --- a/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.h +++ b/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.h @@ -42,12 +42,17 @@ public: // It can be used for all apparences of channel posts. But in rder to merge comments from the previous versions of the post, the list of // previous posts should be supplied. It's optional. If not supplied only the comments of the new version will be displayed. - ChannelsCommentsItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set& older_versions = std::set()); + ChannelsCommentsItem(FeedHolder *feedHolder, + uint32_t feedId, + const RsGxsGroupId& groupId, + const RsGxsMessageId& commentId, + const RsGxsMessageId& threadId, + bool isHome, + bool autoUpdate); // This one is used in channel thread widget. We don't want the group data to reload at every post, so we load it in the hosting // GxsChannelsPostsWidget and pass it to created items. - - ChannelsCommentsItem(FeedHolder *feedHolder, uint32_t feedId, const RsGroupMetaData& group, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set& older_versions = std::set()); + // ChannelsCommentsItem(FeedHolder *feedHolder, uint32_t feedId, const RsGroupMetaData& group, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set& older_versions = std::set()); virtual ~ChannelsCommentsItem(); @@ -55,6 +60,7 @@ public: bool setGroup(const RsGxsChannelGroup& group, bool doFill = true); bool setPost(const RsGxsChannelPost& post, bool doFill = true); + bool setMissingPost(); QString getTitleLabel(); QString getMsgLabel(); @@ -85,8 +91,8 @@ protected: /* GxsFeedItem */ virtual QString messageName(); - virtual void loadMessage(); - virtual void loadComment(); + virtual void loadMessage() override {} + virtual void loadComment() override {} private slots: /* default stuff */ @@ -104,21 +110,20 @@ signals: void vote(const RsGxsGrpMsgIdPair& msgId, bool up); private: - void setup(); - void fill(); - void fillExpandFrame(); + void load(); + void setup(); + void fill(bool missing_post=false); private: bool mInFill; bool mCloseOnRead; bool mLoaded; - bool mLoadingGroup; - bool mLoadingMessage; - bool mLoadingComment; + bool mLoading; RsGroupMetaData mGroupMeta; RsGxsChannelPost mPost; + RsGxsMessageId mThreadId; /** Qt Designer generated object */ Ui::ChannelsCommentsItem *ui;