From fc53af2646cc06520d1bea5d088af725a52db651 Mon Sep 17 00:00:00 2001 From: drbob Date: Fri, 13 Mar 2020 16:44:15 +1100 Subject: [PATCH] TheWire fixup up display of messages Process messages to group replies correctly and sort by age. Expand message display to include replies. Add coloring to distinguish between replies and actual msgs. Enable subscribe / unsubscribe buttons. Add Selection of which set of groups are visible. Add missing setNetworkExchangeService calls for photo + wire services. --- libretroshare/src/gxs/rsgxsnetservice.cc | 2 +- libretroshare/src/rsserver/rsinit.cc | 4 + libretroshare/src/services/p3wire.cc | 7 +- .../src/gui/TheWire/PulseAddDialog.cpp | 3 +- .../src/gui/TheWire/PulseDetails.cpp | 62 ++- retroshare-gui/src/gui/TheWire/PulseDetails.h | 8 +- .../src/gui/TheWire/PulseDetails.ui | 72 +++- retroshare-gui/src/gui/TheWire/PulseItem.cpp | 80 ++-- retroshare-gui/src/gui/TheWire/PulseItem.h | 5 +- retroshare-gui/src/gui/TheWire/PulseItem.ui | 39 +- retroshare-gui/src/gui/TheWire/WireDialog.cpp | 354 ++++++++++++++---- retroshare-gui/src/gui/TheWire/WireDialog.h | 24 +- retroshare-gui/src/gui/TheWire/WireDialog.ui | 13 +- .../src/gui/TheWire/WireGroupDialog.cpp | 2 +- .../src/gui/TheWire/WireGroupItem.cpp | 41 +- .../src/gui/TheWire/WireGroupItem.h | 16 +- .../src/gui/TheWire/WireGroupItem.ui | 13 +- retroshare-gui/src/util/ClickableLabel.h | 6 +- 18 files changed, 582 insertions(+), 169 deletions(-) diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc index 5cebfbfb3..ba2e287ad 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.cc +++ b/libretroshare/src/gxs/rsgxsnetservice.cc @@ -4412,7 +4412,7 @@ void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item,bool item_ if(details.mReputation.mOverallReputationLevel < minReputationForForwardingMessages(grpMeta->mSignFlags, details.mFlags)) { #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " not sending item ID " << (*vit)->mMsgId << ", because the author is flags " << std::hex << details.mFlags << std::dec << " and reputation level " << details.mReputation.mOverallReputationLevel << std::endl; + GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " not sending item ID " << (*vit)->mMsgId << ", because the author is flags " << std::hex << details.mFlags << std::dec << " and reputation level " << (int) details.mReputation.mOverallReputationLevel << std::endl; #endif continue ; } diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index a4e652c4c..25391fcbe 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -1376,6 +1376,8 @@ int RsServer::StartupRetroShare() mPhoto, mPhoto->getServiceInfo(), mReputations, mGxsCircles,mGxsIdService, pgpAuxUtils); + + mPhoto->setNetworkExchangeService(photo_ns); #endif #ifdef RS_USE_WIRE @@ -1391,6 +1393,8 @@ int RsServer::StartupRetroShare() mWire, mWire->getServiceInfo(), mReputations, mGxsCircles,mGxsIdService, pgpAuxUtils); + + mWire->setNetworkExchangeService(wire_ns); #endif // now add to p3service pqih->addService(gxsid_ns, true); diff --git a/libretroshare/src/services/p3wire.cc b/libretroshare/src/services/p3wire.cc index 18119c9a3..d61691f07 100644 --- a/libretroshare/src/services/p3wire.cc +++ b/libretroshare/src/services/p3wire.cc @@ -64,11 +64,14 @@ uint32_t p3Wire::wireAuthenPolicy() // Edits generally need an authors signature. + // Wire requires all TopLevel (Orig/Reply) msgs to be signed with both PUBLISH & AUTHOR. + // Reply References need to be signed by Author. flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; + flag |= GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN; RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - flag |= GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN; - flag |= GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; + // expect the requirements to be the same for RESTRICTED / PRIVATE groups too. + // This needs to be worked through / fully evaluated. RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); diff --git a/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp b/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp index 1e0d58ea6..a23af7f54 100644 --- a/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp @@ -54,7 +54,8 @@ void PulseAddDialog::setReplyTo(RsWirePulse &pulse, std::string &groupName) mReplyGroupName = groupName; { - PulseDetails *details = new PulseDetails(NULL, pulse, groupName, true); + std::map replies; + PulseDetails *details = new PulseDetails(NULL, &pulse, groupName, replies); // add extra widget into layout. QVBoxLayout *vbox = new QVBoxLayout(); vbox->addWidget(details); diff --git a/retroshare-gui/src/gui/TheWire/PulseDetails.cpp b/retroshare-gui/src/gui/TheWire/PulseDetails.cpp index 7bb1f2615..067b1e99e 100644 --- a/retroshare-gui/src/gui/TheWire/PulseDetails.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseDetails.cpp @@ -31,12 +31,14 @@ #include /** Constructor */ -PulseDetails::PulseDetails(PulseHolder *actions, RsWirePulse &pulse, std::string &groupName, bool is_original) -:QWidget(NULL), mActions(actions), mPulse(pulse), mGroupName(groupName), mIsOriginal(is_original) +PulseDetails::PulseDetails(PulseHolder *actions, RsWirePulse *pulse, std::string &groupName, + std::map replies) +:QWidget(NULL), mActions(actions), mPulse(*pulse), mGroupName(groupName) { setupUi(this); setAttribute ( Qt::WA_DeleteOnClose, true ); setup(); + addReplies(replies); } PulseDetails::PulseDetails(PulseHolder *actions, @@ -46,7 +48,7 @@ PulseDetails::PulseDetails(PulseHolder *actions, RsGxsId &parentAuthorId, rstime_t &parentPublishTs, std::string &parentPulseText) -:QWidget(NULL), mActions(actions), mPulse(), mGroupName(parentGroupName), mIsOriginal(false) +:QWidget(NULL), mActions(actions), mPulse(), mGroupName(parentGroupName) { setupUi(this); setAttribute ( Qt::WA_DeleteOnClose, true ); @@ -60,6 +62,15 @@ PulseDetails::PulseDetails(PulseHolder *actions, setup(); } +void PulseDetails::setBackground(QString color) +{ + QWidget *tocolor = this; + QPalette p = tocolor->palette(); + p.setColor(tocolor->backgroundRole(), QColor(color)); + tocolor->setPalette(p); + tocolor->setAutoFillBackground(true); +} + void PulseDetails::setup() { connect(toolButton_expand, SIGNAL(clicked()), this, SLOT(toggle())); @@ -77,6 +88,47 @@ void PulseDetails::setup() // label_icon->setText(); textBrowser->setPlainText(QString::fromStdString(mPulse.mPulseText)); frame_expand->setVisible(false); + + label_replies->setText(""); + frame_replies->setVisible(false); + mHasReplies = false; +} + +void PulseDetails::addReplies(std::map replies) +{ + if (replies.size() == 0) + { + // do nothing. + return; + } + else if (replies.size() == 1) + { + label_replies->setText("1 reply"); + } + else if (replies.size() > 1) + { + label_replies->setText(QString("%1 replies").arg(replies.size())); + } + + // add extra widgets into layout. + QLayout *vbox = frame_replies->layout(); + mHasReplies = true; + + std::map emptyReplies; + std::map::reverse_iterator it; + for (it = replies.rbegin(); it != replies.rend(); it++) + { + // add Ref as child reply. + PulseDetails *pd = new PulseDetails(mActions, + it->second->mRefGroupId, + it->second->mRefGroupName, + it->second->mRefOrigMsgId, + it->second->mRefAuthorId, + it->second->mRefPublishTs, + it->second->mRefPulseText); + pd->setBackground("goldenrod"); + vbox->addWidget(pd); + } } @@ -86,10 +138,14 @@ void PulseDetails::toggle() // switch to minimal view. label_summary->setVisible(true); frame_expand->setVisible(false); + frame_replies->setVisible(false); } else { // switch to expanded view. label_summary->setVisible(false); frame_expand->setVisible(true); + if (mHasReplies) { + frame_replies->setVisible(true); + } } } diff --git a/retroshare-gui/src/gui/TheWire/PulseDetails.h b/retroshare-gui/src/gui/TheWire/PulseDetails.h index 6b063eab9..b6a623f73 100644 --- a/retroshare-gui/src/gui/TheWire/PulseDetails.h +++ b/retroshare-gui/src/gui/TheWire/PulseDetails.h @@ -31,7 +31,8 @@ class PulseDetails : public QWidget, private Ui::PulseDetails Q_OBJECT public: - PulseDetails(PulseHolder *actions, RsWirePulse &pulse, std::string &groupName, bool is_original); + PulseDetails(PulseHolder *actions, RsWirePulse *pulse, std::string &groupName, + std::map replies); // when Reply parent.... PulseDetails(PulseHolder *actions, @@ -44,6 +45,8 @@ public: void setup(); + void setBackground(QString color); + private slots: void toggle(); void follow(); @@ -51,12 +54,13 @@ private slots: void reply(); private: + void addReplies(std::map replies); QString getSummary(); PulseHolder *mActions; RsWirePulse mPulse; std::string mGroupName; - bool mIsOriginal; + bool mHasReplies; }; #endif diff --git a/retroshare-gui/src/gui/TheWire/PulseDetails.ui b/retroshare-gui/src/gui/TheWire/PulseDetails.ui index 3739dd0da..f5f7f7f31 100644 --- a/retroshare-gui/src/gui/TheWire/PulseDetails.ui +++ b/retroshare-gui/src/gui/TheWire/PulseDetails.ui @@ -6,14 +6,14 @@ 0 0 - 750 - 166 + 807 + 231 Form - + @@ -47,9 +47,9 @@ - + - idLabel + # replies @@ -69,7 +69,7 @@ - Summary Text/ date + Summary Text @@ -92,7 +92,7 @@ - TextLabel + DateTime 02/02/20 @@ -134,6 +134,13 @@ + + + + idLabel + + + @@ -171,6 +178,57 @@ + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 30 + 0 + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 75 + true + + + + Replies + + + + + + + + diff --git a/retroshare-gui/src/gui/TheWire/PulseItem.cpp b/retroshare-gui/src/gui/TheWire/PulseItem.cpp index 3b452ffdf..1e73b3364 100644 --- a/retroshare-gui/src/gui/TheWire/PulseItem.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseItem.cpp @@ -44,40 +44,42 @@ PulseItem::PulseItem(PulseHolder *holder, std::string path) } -PulseItem::PulseItem(PulseHolder *holder, RsWirePulse &pulse, RsWireGroup &group) -:QWidget(NULL), mHolder(holder), mType(0) +PulseItem::PulseItem(PulseHolder *holder, RsWirePulse *pulse_ptr, RsWireGroup *group_ptr, std::map replies) +:QWidget(NULL), mHolder(holder), mPulse(*pulse_ptr), mType(0) { setupUi(this); setAttribute ( Qt::WA_DeleteOnClose, true ); QWidget *pulse_widget = widget_parent; // default msg goes into widget_parent. /* if it is a reply */ - if (pulse.mPulseType & WIRE_PULSE_TYPE_REPLY_MSG) { + if (mPulse.mPulseType & WIRE_PULSE_TYPE_REPLY_MSG) { std::cerr << "Installing Reply Msg"; std::cerr << std::endl; - std::cerr << "GroupID: " << pulse.mRefGroupId; + std::cerr << "GroupID: " << mPulse.mRefGroupId; std::cerr << std::endl; - std::cerr << "GroupName: " << pulse.mRefGroupName; + std::cerr << "GroupName: " << mPulse.mRefGroupName; std::cerr << std::endl; - std::cerr << "OrigMsgId: " << pulse.mRefOrigMsgId; + std::cerr << "OrigMsgId: " << mPulse.mRefOrigMsgId; std::cerr << std::endl; - std::cerr << "AuthorId: " << pulse.mRefAuthorId; + std::cerr << "AuthorId: " << mPulse.mRefAuthorId; std::cerr << std::endl; - std::cerr << "PublishTs: " << pulse.mRefPublishTs; + std::cerr << "PublishTs: " << mPulse.mRefPublishTs; std::cerr << std::endl; - std::cerr << "PulseText: " << pulse.mRefPulseText; + std::cerr << "PulseText: " << mPulse.mRefPulseText; std::cerr << std::endl; // fill in the parent. PulseDetails *parent = new PulseDetails( mHolder, - pulse.mRefGroupId, - pulse.mRefGroupName, - pulse.mRefOrigMsgId, - pulse.mRefAuthorId, - pulse.mRefPublishTs, - pulse.mRefPulseText); + mPulse.mRefGroupId, + mPulse.mRefGroupName, + mPulse.mRefOrigMsgId, + mPulse.mRefAuthorId, + mPulse.mRefPublishTs, + mPulse.mRefPulseText); + + parent->setBackground("sienna"); // add extra widget into layout. QVBoxLayout *vbox = new QVBoxLayout(); @@ -88,45 +90,8 @@ PulseItem::PulseItem(PulseHolder *holder, RsWirePulse &pulse, RsWireGroup &group // if its a reply, the real msg goes into reply slot. pulse_widget = widget_reply; } - else if (pulse.mPulseType & WIRE_PULSE_TYPE_REPLY_REFERENCE) + else { - // THIS IS A FAKE ONE... LEAVE IN UNTIL ITS HANDLED ELSEWHERE. - // NB: PARENT PublishTS and AuthorID appear wrong... - - std::cerr << "Installing Ref Msg"; - std::cerr << std::endl; - std::cerr << "GroupID: " << pulse.mRefGroupId; - std::cerr << std::endl; - std::cerr << "GroupName: " << pulse.mRefGroupName; - std::cerr << std::endl; - std::cerr << "OrigMsgId: " << pulse.mRefOrigMsgId; - std::cerr << std::endl; - std::cerr << "AuthorId: " << pulse.mRefAuthorId; - std::cerr << std::endl; - std::cerr << "PublishTs: " << pulse.mRefPublishTs; - std::cerr << std::endl; - std::cerr << "PulseText: " << pulse.mRefPulseText; - std::cerr << std::endl; - - // fill in the parent. - PulseDetails *parent = new PulseDetails( - mHolder, - pulse.mRefGroupId, - pulse.mRefGroupName, - pulse.mRefOrigMsgId, - pulse.mRefAuthorId, - pulse.mRefPublishTs, - pulse.mRefPulseText); - - // add extra widget into layout. - QVBoxLayout *vbox = new QVBoxLayout(); - vbox->addWidget(parent); - vbox->setContentsMargins(0,0,0,0); - widget_reply->setLayout(vbox); - - // if its a REF, the real msg goes into parent slot. - pulse_widget = widget_parent; - } else { // ORIGINAL PULSE. // hide widget_reply, as it will be empty. widget_reply->setVisible(false); @@ -135,7 +100,7 @@ PulseItem::PulseItem(PulseHolder *holder, RsWirePulse &pulse, RsWireGroup &group { std::cerr << "Adding Main Message"; std::cerr << std::endl; - PulseDetails *details = new PulseDetails(mHolder, pulse, group.mMeta.mGroupName, true); + PulseDetails *details = new PulseDetails(mHolder, &mPulse, group_ptr->mMeta.mGroupName, replies); // add extra widget into layout. QVBoxLayout *vbox = new QVBoxLayout(); @@ -144,10 +109,13 @@ PulseItem::PulseItem(PulseHolder *holder, RsWirePulse &pulse, RsWireGroup &group vbox->setContentsMargins(0,0,0,0); pulse_widget->setLayout(vbox); pulse_widget->setVisible(true); - // details->toggle(); } } +rstime_t PulseItem::publishTs() +{ + return mPulse.mMeta.mPublishTs; +} void PulseItem::removeItem() { @@ -178,6 +146,8 @@ void PulseItem::mousePressEvent(QMouseEvent *event) setSelected(true); QWidget::mousePressEvent(event); + + mHolder->notifyPulseSelection(this); } const QPixmap *PulseItem::getPixmap() diff --git a/retroshare-gui/src/gui/TheWire/PulseItem.h b/retroshare-gui/src/gui/TheWire/PulseItem.h index 03ac190fb..0e7395e0e 100644 --- a/retroshare-gui/src/gui/TheWire/PulseItem.h +++ b/retroshare-gui/src/gui/TheWire/PulseItem.h @@ -32,7 +32,7 @@ class PulseHolder public: virtual ~PulseHolder() {} virtual void deletePulseItem(PulseItem *, uint32_t ptype) = 0; - virtual void notifySelection(PulseItem *item, int ptype) = 0; + virtual void notifyPulseSelection(PulseItem *item) = 0; // Actions. virtual void follow(RsGxsGroupId &groupId) = 0; @@ -47,8 +47,9 @@ class PulseItem : public QWidget, private Ui::PulseItem public: PulseItem(PulseHolder *holder, std::string url); - PulseItem(PulseHolder *holder, RsWirePulse &pulse, RsWireGroup &group); + PulseItem(PulseHolder *holder, RsWirePulse *pulse_ptr, RsWireGroup *group_ptr, std::map replies); + rstime_t publishTs(); void removeItem(); void setSelected(bool on); diff --git a/retroshare-gui/src/gui/TheWire/PulseItem.ui b/retroshare-gui/src/gui/TheWire/PulseItem.ui index c032446a8..f12b3bda0 100644 --- a/retroshare-gui/src/gui/TheWire/PulseItem.ui +++ b/retroshare-gui/src/gui/TheWire/PulseItem.ui @@ -25,6 +25,18 @@ + + 2 + + + 2 + + + 2 + + + 2 + @@ -52,6 +64,21 @@ border-radius: 10px} QFrame::Raised + + 1 + + + 5 + + + 2 + + + 5 + + + 2 + @@ -81,7 +108,7 @@ border-radius: 10px} 10 - 40 + 0 @@ -93,8 +120,8 @@ border-radius: 10px} - 50 - 20 + 30 + 0 @@ -113,8 +140,8 @@ border-radius: 10px} - 50 - 20 + 30 + 0 @@ -127,7 +154,7 @@ border-radius: 10px} 10 - 40 + 0 diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.cpp b/retroshare-gui/src/gui/TheWire/WireDialog.cpp index 7dd1e1199..e29a82137 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/WireDialog.cpp @@ -37,10 +37,20 @@ * */ +#define GROUP_SET_ALL (0) +#define GROUP_SET_OWN (1) +#define GROUP_SET_SUBSCRIBED (2) +#define GROUP_SET_AUTO (3) +#define GROUP_SET_RECOMMENDED (4) +#define GROUP_SET_OTHERS (5) + + +#define WIRE_TOKEN_TYPE_SUBSCRIBE_CHANGE 1 + /** Constructor */ WireDialog::WireDialog(QWidget *parent) -: MainPage(parent) +: MainPage(parent), mGroupSet(GROUP_SET_ALL) { ui.setupUi(this); @@ -52,6 +62,8 @@ WireDialog::WireDialog(QWidget *parent) connect( ui.pushButton_Post, SIGNAL(clicked()), this, SLOT(createPulse())); connect( ui.toolButton_refresh, SIGNAL(clicked()), this, SLOT(refreshGroups())); + connect(ui.comboBox_groupSet, SIGNAL(currentIndexChanged(int)), this, SLOT(selectGroupSet(int))); + QTimer *timer = new QTimer(this); timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); timer->start(1000); @@ -67,12 +79,6 @@ void WireDialog::refreshGroups() requestGroupData(); } -void WireDialog::addItem(QWidget *item) -{ - QLayout *alayout = ui.scrollAreaWidgetContents->layout(); - alayout->addWidget(item); -} - void WireDialog::addGroup(QWidget *item) { @@ -81,19 +87,11 @@ void WireDialog::addGroup(QWidget *item) } // PulseHolder interface. -void WireDialog::deletePulseItem(PulseItem *item, uint32_t type) +void WireDialog::deletePulseItem(PulseItem * /* item */, uint32_t /* type */) { return; } -void WireDialog::notifySelection(PulseItem *item, int ptype) -{ - std::cerr << "WireDialog::notifySelection() from : " << ptype << " " << item; - std::cerr << std::endl; - - notifyPulseSelection(item); -} - // Actions from PulseHolder. void WireDialog::follow(RsGxsGroupId &groupId) @@ -148,9 +146,6 @@ void WireDialog::reply(RsWirePulse &pulse, std::string &groupName) void WireDialog::notifyPulseSelection(PulseItem *item) { - std::cerr << "WireDialog::notifyPulseSelection() from : " << item; - std::cerr << std::endl; - if (mPulseSelected) { std::cerr << "WireDialog::notifyPulseSelection() unselecting old one : " << mPulseSelected; @@ -158,11 +153,42 @@ void WireDialog::notifyPulseSelection(PulseItem *item) mPulseSelected->setSelected(false); } - mPulseSelected = item; } + +void WireDialog::subscribe(RsGxsGroupId &groupId) +{ + uint32_t token; + rsWire->subscribeToGroup(token, groupId, true); + mWireQueue->queueRequest(token, TOKENREQ_GROUPINFO, RS_TOKREQ_ANSTYPE_ACK, WIRE_TOKEN_TYPE_SUBSCRIBE_CHANGE); +} + +void WireDialog::unsubscribe(RsGxsGroupId &groupId) +{ + uint32_t token; + rsWire->subscribeToGroup(token, groupId, false); + mWireQueue->queueRequest(token, TOKENREQ_GROUPINFO, RS_TOKREQ_ANSTYPE_ACK, WIRE_TOKEN_TYPE_SUBSCRIBE_CHANGE); +} + +void WireDialog::notifyGroupSelection(WireGroupItem *item) +{ + std::cerr << "WireDialog::notifyGroupSelection() from : " << item; + std::cerr << std::endl; + + if (mGroupSelected) + { + std::cerr << "WireDialog::notifyGroupSelection() unselecting old one : " << mGroupSelected; + std::cerr << std::endl; + + mGroupSelected->setSelected(false); + } + + mGroupSelected = item; +} + + void WireDialog::checkUpdate() { #if 0 @@ -207,22 +233,55 @@ void WireDialog::createPulse() mAddDialog->show(); } -void WireDialog::addPulse(RsWirePulse &pulse, RsWireGroup &group) +void WireDialog::addPulse(RsWirePulse *pulse, RsWireGroup *group, + std::map replies) { - std::cerr << "WireDialog::addPulse() GroupId : " << pulse.mMeta.mGroupId; - std::cerr << " MsgId : " << pulse.mMeta.mGroupId; + std::cerr << "WireDialog::addPulse() GroupId : " << pulse->mMeta.mGroupId; + std::cerr << " OrigMsgId : " << pulse->mMeta.mOrigMsgId; + std::cerr << " Replies : " << replies.size(); std::cerr << std::endl; - QWidget *item = new PulseItem(this, pulse, group); - addItem(item); + PulseItem *pulseItem = new PulseItem(this, pulse, group, replies); + + /* ensure its a boxlayout */ + QLayout *alayout = ui.scrollAreaWidgetContents->layout(); + QBoxLayout *boxlayout = dynamic_cast(alayout); + if (boxlayout == NULL) { + std::cerr << "WireDialog::addPulse() ERROR not boxlayout, inserting at end"; + std::cerr << std::endl; + alayout->addWidget(pulseItem); + return; + } + + /* iterate through layout, and insert at the correct time */ + for(int i = 0; i < alayout->count(); i++) + { + QLayoutItem *layoutItem = boxlayout->itemAt(i); + PulseItem *pitem = dynamic_cast(layoutItem->widget()); + if (pitem != NULL) + { + if (pitem->publishTs() < pulseItem->publishTs()) + { + std::cerr << "WireDialog::addPulse() Inserting at index: " << i; + std::cerr << std::endl; + /* insert at this index */ + boxlayout->insertWidget(i, pulseItem); + return; + } + } + } + // last item. + std::cerr << "WireDialog::addPulse() Inserting at end"; + std::cerr << std::endl; + boxlayout->addWidget(pulseItem); } -void WireDialog::addGroup(RsWireGroup &group) +void WireDialog::addGroup(const RsWireGroup &group) { std::cerr << "WireDialog::addGroup() GroupId : " << group.mMeta.mGroupId; std::cerr << std::endl; - addGroup(new WireGroupItem(group)); + addGroup(new WireGroupItem(this, group)); } void WireDialog::deletePulses() @@ -261,11 +320,6 @@ void WireDialog::deleteGroups() std::cerr << "WireDialog::deleteGroups()"; std::cerr << std::endl; - mAllGroups.clear(); - mOwnGroups.clear(); - ui.groupChooser->clear(); - - QLayout *alayout = ui.scrollAreaWidgetContents_groups->layout(); QLayoutItem *item; int i = 0; @@ -294,6 +348,10 @@ void WireDialog::deleteGroups() void WireDialog::updateGroups(std::vector& groups) { + mAllGroups.clear(); + mOwnGroups.clear(); + ui.groupChooser->clear(); + std::vector::const_iterator it; for(it = groups.begin(); it != groups.end(); it++) { // save list of all groups. @@ -310,8 +368,62 @@ void WireDialog::updateGroups(std::vector& groups) } -// LOAD DATA............................................... +void WireDialog::selectGroupSet(int index) +{ + std::cerr << "WireDialog::selectGroupSet(" << index << ")"; + std::cerr << std::endl; + mGroupSet = index; + if (mGroupSet < 0) { + mGroupSet = GROUP_SET_ALL; + } + showGroups(); +} + +void WireDialog::showGroups() +{ + deleteGroups(); + deletePulses(); + + /* depends on the comboBox */ + std::map::const_iterator it; + for (it = mAllGroups.begin(); it != mAllGroups.end(); it++) + { + bool add = (mGroupSet == GROUP_SET_ALL); + if (it->second.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) { + if (mGroupSet == GROUP_SET_OWN) { + add = true; + } + } + else if (it->second.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) { + if (mGroupSet == GROUP_SET_SUBSCRIBED) { + add = true; + } + if (mGroupSet == GROUP_SET_AUTO) { + add = true; + } + if (mGroupSet == GROUP_SET_RECOMMENDED) { + add = true; + } + } + else { + if (mGroupSet == GROUP_SET_OTHERS) { + add = true; + } + } + + if (add) { + addGroup(it->second); + // request data. + std::list grpIds; + grpIds.push_back(it->second.mMeta.mGroupId); + requestPulseData(grpIds); + } + } +} + + +// LOAD DATA............................................... void WireDialog::requestGroupData() { @@ -329,29 +441,12 @@ bool WireDialog::loadGroupData(const uint32_t &token) std::cerr << "WireDialog::loadGroupData()"; std::cerr << std::endl; - deleteGroups(); - deletePulses(); - std::vector groups; rsWire->getGroupData(token, groups); - std::vector::iterator vit = groups.begin(); - - for(; vit != groups.end(); ++vit) - { - RsWireGroup& group = *vit; - - std::cerr << " WireDialog::addGroup() GroupId: " << group.mMeta.mGroupId << std::endl; - - addGroup(group); - - std::list grpIds; - grpIds.push_back(group.mMeta.mGroupId); - requestPulseData(grpIds); - } - // save list of groups. updateGroups(groups); + showGroups(); return true; } @@ -367,43 +462,168 @@ void WireDialog::requestPulseData(const std::list& grpIds) mWireQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds, 0); } + +/* LoadPulseData... + * + * group into threads, using std::map + * then sort by publishTS, using std::map + * then add into gui. + * - use pointers to avoid copying everywhere. + * + * should we mutex Groups, or copy so we don't lose a pointer? + * should be fine, as mAllGroups only modified from loadData calls. + ****** + * + * NB: Potentially, this should be changed to use GXS to do the bulk of the work. + * - request Top-Level Msgs, sorted by PublishTS. + * - Insert into GUI. + * - for each request children Msg, and fill in "replies" + * + * This needs sorted option on GXS Data fetch. + */ + +class PulseReplySet +{ +public: + PulseReplySet() : group(NULL), msg(NULL) {} + PulseReplySet(RsWirePulse *m, RsWireGroup *g) + : group(g), msg(m) {} + + RsWireGroup *group; + RsWirePulse *msg; + std::map replies; // orig ID -> replies. +}; + +class PulseOrderedReply +{ +public: + PulseOrderedReply() : group(NULL), msg(NULL) {} + PulseOrderedReply(RsWirePulse *m, RsWireGroup *g) + : group(g), msg(m) {} + + RsWireGroup *group; + RsWirePulse *msg; + std::map replies; // publish -> replies. +}; + bool WireDialog::loadPulseData(const uint32_t &token) { std::cerr << "WireDialog::loadPulseData()"; std::cerr << std::endl; - // clearPulses(); - std::vector pulses; rsWire->getPulseData(token, pulses); + std::list references; + std::map pulseGrouping; + std::vector::iterator vit = pulses.begin(); for(; vit != pulses.end(); vit++) { RsWirePulse& pulse = *vit; - - RsGxsGroupId &gid = pulse.mMeta.mGroupId; - std::map::iterator mit = mAllGroups.find(gid); - if (mit != mAllGroups.end()) + if (pulse.mPulseType & WIRE_PULSE_TYPE_REPLY_REFERENCE) { - RsWireGroup &group = mit->second; - addPulse(pulse, group); - std::cerr << "WireDialog::loadPulseData() GroupId: " << pulse.mMeta.mGroupId; + // store references to add in later. + std::cerr << "WireDialog::loadPulseData() REF: GroupId: " << pulse.mMeta.mGroupId; std::cerr << " PulseId: " << pulse.mMeta.mMsgId; std::cerr << std::endl; + references.push_back(&pulse); } else { - std::cerr << "WireDialog::loadPulseData() ERROR Missing GroupId: " << pulse.mMeta.mGroupId; - std::cerr << " PulseId: " << pulse.mMeta.mMsgId; - std::cerr << std::endl; + RsGxsGroupId &gid = pulse.mMeta.mGroupId; + std::map::iterator git = mAllGroups.find(gid); + if (git != mAllGroups.end()) + { + RsWireGroup &group = git->second; + std::cerr << "WireDialog::loadPulseData() MSG: GroupId: " << pulse.mMeta.mGroupId; + std::cerr << " PulseId: " << pulse.mMeta.mMsgId; + std::cerr << std::endl; + + // install into pulseGrouping. + pulseGrouping[pulse.mMeta.mOrigMsgId] = PulseReplySet(&pulse, &group); + } + else + { + std::cerr << "WireDialog::loadPulseData() ERROR Missing GroupId: " << pulse.mMeta.mGroupId; + std::cerr << " PulseId: " << pulse.mMeta.mMsgId; + std::cerr << std::endl; + } } } - // updatePulses(); + // add references. + std::list::iterator lrit; + for(lrit = references.begin(); lrit != references.end(); lrit++) + { + std::map::iterator pgit; + pgit = pulseGrouping.find((*lrit)->mMeta.mThreadId); + if (pgit != pulseGrouping.end()) + { + // install into reply map. + // TODO handle Edits / Latest MSGS. + std::map::iterator rmit; + rmit = pgit->second.replies.find((*lrit)->mMeta.mOrigMsgId); + if (rmit == pgit->second.replies.end()) + { + std::cerr << "WireDialog::loadPulseData() Installing REF: " << (*lrit)->mMeta.mOrigMsgId; + std::cerr << " to threadId: " << (*lrit)->mMeta.mThreadId; + std::cerr << std::endl; + pgit->second.replies[(*lrit)->mMeta.mOrigMsgId] = (*lrit); + } + else + { + std::cerr << "WireDialog::loadPulseData() ERROR Duplicate reply REF: " << (*lrit)->mMeta.mOrigMsgId; + std::cerr << std::endl; + } + } + else + { + // no original msg for REF. + std::cerr << "WireDialog::loadPulseData() ERROR No matching ThreadId REF: " << (*lrit)->mMeta.mThreadId; + std::cerr << std::endl; + } + } + references.clear(); + + // sort by publish time. + std::map pulseOrdering; + std::map::iterator pgit; + for(pgit = pulseGrouping.begin(); pgit != pulseGrouping.end(); pgit++) + { + PulseOrderedReply &msg = pulseOrdering[pgit->second.msg->mMeta.mPublishTs] = + PulseOrderedReply(pgit->second.msg, pgit->second.group); + std::map::iterator rmit; + for(rmit = pgit->second.replies.begin(); + rmit != pgit->second.replies.end(); rmit++) + { + msg.replies[rmit->second->mMeta.mPublishTs] = rmit->second; + } + } + + // now add to the GUI. + std::map::reverse_iterator poit; + for (poit = pulseOrdering.rbegin(); poit != pulseOrdering.rend(); poit++) + { + // add into GUI should insert at correct time point, amongst all other ones. + addPulse(poit->second.msg, poit->second.group, poit->second.replies); + } + return true; } +void WireDialog::acknowledgeGroup(const uint32_t &token, const uint32_t &userType) +{ + /* reload groups */ + std::cerr << "WireDialog::acknowledgeGroup(usertype: " << userType << ")"; + std::cerr << std::endl; + + RsGxsGroupId grpId; + rsWire->acknowledgeGrp(token, grpId); + + refreshGroups(); +} + /**************************** Request / Response Filling of Data ************************/ @@ -426,9 +646,9 @@ void WireDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) case RS_TOKREQ_ANSTYPE_DATA: loadGroupData(req.mToken); break; - // case RS_TOKREQ_ANSTYPE_ACK: - // acknowledgeGroup(req.mToken); - // break; + case RS_TOKREQ_ANSTYPE_ACK: + acknowledgeGroup(req.mToken, req.mUserType); + break; default: std::cerr << "WireDialog::loadRequest() ERROR: GROUP: INVALID ANS TYPE"; std::cerr << std::endl; diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.h b/retroshare-gui/src/gui/TheWire/WireDialog.h index e50823ffd..738cedffd 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.h +++ b/retroshare-gui/src/gui/TheWire/WireDialog.h @@ -29,13 +29,14 @@ #include #include "gui/TheWire/PulseItem.h" +#include "gui/TheWire/WireGroupItem.h" #include "gui/TheWire/PulseAddDialog.h" #include "util/TokenQueue.h" #define IMAGE_WIRE ":/images/kgames.png" -class WireDialog : public MainPage, public TokenResponse, public PulseHolder +class WireDialog : public MainPage, public TokenResponse, public PulseHolder, public WireGroupHolder { Q_OBJECT @@ -48,13 +49,17 @@ public: // PulseHolder interface. virtual void deletePulseItem(PulseItem *, uint32_t type); - virtual void notifySelection(PulseItem *item, int ptype); + virtual void notifyPulseSelection(PulseItem *item); virtual void follow(RsGxsGroupId &groupId); virtual void rate(RsGxsId &authorId); virtual void reply(RsWirePulse &pulse, std::string &groupName); - void notifyPulseSelection(PulseItem *item); + + // WireGroupHolder interface. + virtual void subscribe(RsGxsGroupId &groupId); + virtual void unsubscribe(RsGxsGroupId &groupId); + virtual void notifyGroupSelection(WireGroupItem *item); private slots: @@ -62,31 +67,38 @@ private slots: void createPulse(); void checkUpdate(); void refreshGroups(); + void selectGroupSet(int index); private: - void addItem(QWidget *item); void addGroup(QWidget *item); - void addPulse(RsWirePulse &pulse, RsWireGroup &group); - void addGroup(RsWireGroup &group); + void addPulse(RsWirePulse *pulse, RsWireGroup *group, + std::map replies); + + void addGroup(const RsWireGroup &group); void deletePulses(); void deleteGroups(); + void showGroups(); void updateGroups(std::vector &groups); // Loading Data. void requestGroupData(); bool loadGroupData(const uint32_t &token); + void acknowledgeGroup(const uint32_t &token, const uint32_t &userType); void requestPulseData(const std::list& grpIds); bool loadPulseData(const uint32_t &token); virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); + int mGroupSet; + PulseAddDialog *mAddDialog; PulseItem *mPulseSelected; + WireGroupItem *mGroupSelected; TokenQueue *mWireQueue; diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.ui b/retroshare-gui/src/gui/TheWire/WireDialog.ui index ee69ee56b..84f76e5b1 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.ui +++ b/retroshare-gui/src/gui/TheWire/WireDialog.ui @@ -116,7 +116,7 @@ 0 0 - 567 + 434 412 @@ -234,7 +234,7 @@ - 200 + 400 16777215 @@ -270,7 +270,7 @@ 0 0 - 129 + 262 416 @@ -296,7 +296,12 @@ - + + + + All + + Yourself diff --git a/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp b/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp index 119d29a9f..0bc0470b3 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp @@ -125,7 +125,7 @@ bool WireGroupDialog::service_CreateGroup(uint32_t &token, const RsGroupMetaData return true; } -bool WireGroupDialog::service_EditGroup(uint32_t &token, RsGroupMetaData &editedMeta) +bool WireGroupDialog::service_EditGroup(uint32_t & /* token */, RsGroupMetaData &editedMeta) { RsWireGroup grp; prepareWireGroup(grp, editedMeta); diff --git a/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp b/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp index 5c5606943..d1f2ae1e4 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp +++ b/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp @@ -30,8 +30,8 @@ /** Constructor */ -WireGroupItem::WireGroupItem(RsWireGroup grp) -:QWidget(NULL), mGroup(grp), mType(0) +WireGroupItem::WireGroupItem(WireGroupHolder *holder, const RsWireGroup &grp) +:QWidget(NULL), mHolder(holder), mGroup(grp) { setupUi(this); setAttribute ( Qt::WA_DeleteOnClose, true ); @@ -42,10 +42,31 @@ WireGroupItem::WireGroupItem(RsWireGroup grp) void WireGroupItem::setup() { label_groupName->setText(QString::fromStdString(mGroup.mMeta.mGroupName)); - // label_authorId->setText(mGroup.mMeta.mAuthorId); + label_authorId->setId(mGroup.mMeta.mAuthorId); frame_details->setVisible(false); connect(toolButton_show, SIGNAL(clicked()), this, SLOT(show())); + connect(toolButton_subscribe, SIGNAL(clicked()), this, SLOT(subscribe())); + setGroupSet(); +} + +void WireGroupItem::setGroupSet() +{ + if (mGroup.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) { + toolButton_type->setText("Own"); + toolButton_subscribe->setText("N/A"); + toolButton_subscribe->setEnabled(false); + } + else if (mGroup.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) + { + toolButton_type->setText("Subcribed"); + toolButton_subscribe->setText("Unsubcribe"); + } + else + { + toolButton_type->setText("Other"); + toolButton_subscribe->setText("Subcribe"); + } } void WireGroupItem::show() @@ -53,12 +74,24 @@ void WireGroupItem::show() frame_details->setVisible(!frame_details->isVisible()); } +void WireGroupItem::subscribe() +{ + if (mGroup.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) + { + mHolder->unsubscribe(mGroup.mMeta.mGroupId); + } + else + { + mHolder->subscribe(mGroup.mMeta.mGroupId); + } +} + void WireGroupItem::removeItem() { } -void WireGroupItem::setSelected(bool on) +void WireGroupItem::setSelected(bool /* on */) { } diff --git a/retroshare-gui/src/gui/TheWire/WireGroupItem.h b/retroshare-gui/src/gui/TheWire/WireGroupItem.h index 9f6eac14f..82863ea89 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupItem.h +++ b/retroshare-gui/src/gui/TheWire/WireGroupItem.h @@ -27,12 +27,22 @@ class WireGroupItem; +class WireGroupHolder +{ +public: + virtual ~WireGroupHolder() {} + virtual void subscribe(RsGxsGroupId &groupId) = 0; + virtual void unsubscribe(RsGxsGroupId &groupId) = 0; + + virtual void notifyGroupSelection(WireGroupItem *item) = 0; +}; + class WireGroupItem : public QWidget, private Ui::WireGroupItem { Q_OBJECT public: - WireGroupItem(RsWireGroup grp); + WireGroupItem(WireGroupHolder *holder, const RsWireGroup &grp); void removeItem(); @@ -43,15 +53,17 @@ public: private slots: void show(); + void subscribe(); protected: void mousePressEvent(QMouseEvent *event); private: void setup(); + void setGroupSet(); + WireGroupHolder *mHolder; RsWireGroup mGroup; - uint32_t mType; bool mSelected; }; diff --git a/retroshare-gui/src/gui/TheWire/WireGroupItem.ui b/retroshare-gui/src/gui/TheWire/WireGroupItem.ui index f5939e03b..a71e1ed23 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupItem.ui +++ b/retroshare-gui/src/gui/TheWire/WireGroupItem.ui @@ -46,7 +46,7 @@ - + Type @@ -71,7 +71,7 @@ - + GxsIdLabel @@ -91,7 +91,7 @@ - + Sub/Un @@ -105,6 +105,13 @@ + + + GxsIdLabel + QLabel +
gui/gxs/GxsIdLabel.h
+
+
diff --git a/retroshare-gui/src/util/ClickableLabel.h b/retroshare-gui/src/util/ClickableLabel.h index 520608668..65070fd67 100644 --- a/retroshare-gui/src/util/ClickableLabel.h +++ b/retroshare-gui/src/util/ClickableLabel.h @@ -38,10 +38,10 @@ signals: protected: void mousePressEvent(QMouseEvent* event); - void enterEvent(QEvent *ev) override { setStyleSheet("QLabel { border: 2px solid #039bd5; }");} + void enterEvent(QEvent * /* ev */ ) override { setStyleSheet("QLabel { border: 2px solid #039bd5; }");} - void leaveEvent(QEvent *ev) override { setStyleSheet("QLabel { border: 2px solid #CCCCCC; border-radius: 3px; }");} + void leaveEvent(QEvent * /* ev */ ) override { setStyleSheet("QLabel { border: 2px solid #CCCCCC; border-radius: 3px; }");} }; -#endif // CLICKABLELABEL_H \ No newline at end of file +#endif // CLICKABLELABEL_H