From 24fd4ae3e77007cb77a336a28b5ea629efc24c3b Mon Sep 17 00:00:00 2001 From: drbob Date: Sat, 29 Feb 2020 11:47:00 +1100 Subject: [PATCH 1/2] Get the basics of TheWire service working Added REF fields to Wire Msgs to allow replys to work well. Added description of how the Message fields should be used. Added WireGroupDialog for creation of WireGroups. Updated PulseAddDialog to support publishing Pulses and Replies. Added classes to display Pulses / Groups. Added single selection point of WireGroup for publishing. Added basic "refresh" to reload new GXS data. --- libretroshare/src/retroshare/rswire.h | 72 +- libretroshare/src/rsitems/rswireitems.cc | 38 +- libretroshare/src/rsserver/rsinit.cc | 7 +- libretroshare/src/services/p3wire.cc | 18 +- libretroshare/src/services/p3wire.h | 34 +- .../src/gui/TheWire/PulseAddDialog.cpp | 352 +++++---- .../src/gui/TheWire/PulseAddDialog.h | 34 +- .../src/gui/TheWire/PulseAddDialog.ui | 373 ++++----- .../src/gui/TheWire/PulseDetails.cpp | 144 ++++ retroshare-gui/src/gui/TheWire/PulseDetails.h | 62 ++ .../src/gui/TheWire/PulseDetails.ui | 185 +++++ retroshare-gui/src/gui/TheWire/PulseItem.cpp | 141 +++- retroshare-gui/src/gui/TheWire/PulseItem.h | 37 +- retroshare-gui/src/gui/TheWire/PulseItem.ui | 257 +++---- .../src/gui/TheWire/TheWire_images.qrc | 15 + retroshare-gui/src/gui/TheWire/WireDialog.cpp | 711 +++++++++--------- retroshare-gui/src/gui/TheWire/WireDialog.h | 64 +- retroshare-gui/src/gui/TheWire/WireDialog.ui | 383 +++++----- .../src/gui/TheWire/WireGroupDialog.cpp | 180 +++++ .../src/gui/TheWire/WireGroupDialog.h | 46 ++ .../src/gui/TheWire/WireGroupItem.cpp | 92 +++ .../src/gui/TheWire/WireGroupItem.h | 58 ++ .../src/gui/TheWire/WireGroupItem.ui | 110 +++ 23 files changed, 2303 insertions(+), 1110 deletions(-) create mode 100644 retroshare-gui/src/gui/TheWire/PulseDetails.cpp create mode 100644 retroshare-gui/src/gui/TheWire/PulseDetails.h create mode 100644 retroshare-gui/src/gui/TheWire/PulseDetails.ui create mode 100644 retroshare-gui/src/gui/TheWire/TheWire_images.qrc create mode 100644 retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp create mode 100644 retroshare-gui/src/gui/TheWire/WireGroupDialog.h create mode 100644 retroshare-gui/src/gui/TheWire/WireGroupItem.cpp create mode 100644 retroshare-gui/src/gui/TheWire/WireGroupItem.h create mode 100644 retroshare-gui/src/gui/TheWire/WireGroupItem.ui diff --git a/libretroshare/src/retroshare/rswire.h b/libretroshare/src/retroshare/rswire.h index 580d3f279..f7225d581 100644 --- a/libretroshare/src/retroshare/rswire.h +++ b/libretroshare/src/retroshare/rswire.h @@ -3,7 +3,7 @@ * * * libretroshare: retroshare core library * * * - * Copyright 2012-2012 by Robert Fernie * + * Copyright 2012-2020 by Robert Fernie * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -45,11 +45,7 @@ class RsWireGroup /*********************************************************************** - * So pulses operate in the following modes. - * - * => Standard, a post to your own group. - * => @User, gets duplicated on each user's group. - * => RT, duplicated as child of original post. + * RsWire - is intended to be a Twitter clone - but fully decentralised. * * From Twitter: * twitter can be: embedded, replied to, favourited, unfavourited, @@ -73,6 +69,36 @@ class RsWirePlace }; +/************************************************************************ + * Pulse comes in three flavours. + * + * + * Original Msg Pulse + * - Spontaneous msg, on your own group. + * - mPulseType = WIRE_PULSE_TYPE_ORIGINAL_MSG + * - Ref fields are empty. + * + * Reply to a Pulse (i.e Retweet), has two parts. + * as we want the retweet to reference the original, and the original to know about reply. + * This info will be duplicated in two msgs - but allow data to spread easier. + * + * Reply Msg Pulse, will be Top-Level Msg on Publisher's Group. + * - mPulseMode = WIRE_PULSE_TYPE_REPLY_MSG + * - Ref fields refer to Parent (InReplyTo) Msg. + * + * Reply Reference, is Child Msg of Parent Msg, on Parent Publisher's Group. + * - mPulseMode = WIRE_PULSE_TYPE_REPLY_REFERENCE + * - Ref fields refer to Reply Msg. + * - NB: This Msg requires Parent Msg for complete info, while other two are self-contained. + ***********************************************************************/ + +#define WIRE_PULSE_TYPE_ORIGINAL_MSG (0x0001) +#define WIRE_PULSE_TYPE_REPLY_MSG (0x0002) +#define WIRE_PULSE_TYPE_REPLY_REFERENCE (0x0004) + +#define WIRE_PULSE_TYPE_SENTIMENT_POSITIVE (0x0010) +#define WIRE_PULSE_TYPE_SENTIMENT_NEUTRAL (0x0020) +#define WIRE_PULSE_TYPE_SENTIMENT_NEGATIVE (0x0040) class RsWirePulse { @@ -80,19 +106,26 @@ class RsWirePulse RsMsgMetaData mMeta; - std::string mPulseText; // all the text is stored here. - std::string mHashTags; + // Store actual Pulse here. + std::string mPulseText; -// These will be added at some point. -// std::string mInReplyPulse; + uint32_t mPulseType; -// uint32_t mPulseFlags; + // These Ref to the related (parent or reply) if reply (MODE_REPLY_MSG set) + // Mode REPLY_MSG only REPLY_REFERENCE + RsGxsGroupId mRefGroupId; // PARENT_GrpId REPLY_GrpId + std::string mRefGroupName; // PARENT_GrpName REPLY_GrpName + RsGxsMessageId mRefOrigMsgId; // PARENT_OrigMsgId REPLY_OrigMsgId + RsGxsId mRefAuthorId; // PARENT_AuthorId REPLY_AuthorId + rstime_t mRefPublishTs; // PARENT_PublishTs REPLY_PublishTs + std::string mRefPulseText; // PARENT_PulseText REPLY_PulseText -// std::list mMentions; -// std::list mHashTags; -// std::list mUrls; - -// RsWirePlace mPlace; + // Open Question. Do we want these additional fields? + // These can potentially be added at some point. + // std::list mMentions; + // std::list mHashTags; + // std::list mUrls; + // RsWirePlace mPlace; }; @@ -107,6 +140,13 @@ class RsWire: public RsGxsIfaceHelper explicit RsWire(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} virtual ~RsWire() {} + /*! + * To acquire a handle to token service handler + * needed to make requests to the service + * @return handle to token service for this gxs service + */ + virtual RsTokenService* getTokenService() = 0; + /* Specific Service Data */ virtual bool getGroupData(const uint32_t &token, std::vector &groups) = 0; virtual bool getPulseData(const uint32_t &token, std::vector &pulses) = 0; diff --git a/libretroshare/src/rsitems/rswireitems.cc b/libretroshare/src/rsitems/rswireitems.cc index c00012975..65360dbf4 100644 --- a/libretroshare/src/rsitems/rswireitems.cc +++ b/libretroshare/src/rsitems/rswireitems.cc @@ -29,16 +29,16 @@ RsItem *RsGxsWireSerialiser::create_item(uint16_t service,uint8_t item_subtype) const { - if(service != RS_SERVICE_GXS_TYPE_WIRE) - return NULL ; + if(service != RS_SERVICE_GXS_TYPE_WIRE) + return NULL ; - switch(item_subtype) - { - case RS_PKT_SUBTYPE_WIRE_GROUP_ITEM: return new RsGxsWireGroupItem(); - case RS_PKT_SUBTYPE_WIRE_PULSE_ITEM: return new RsGxsWirePulseItem(); - default: - return NULL ; - } + switch(item_subtype) + { + case RS_PKT_SUBTYPE_WIRE_GROUP_ITEM: return new RsGxsWireGroupItem(); + case RS_PKT_SUBTYPE_WIRE_PULSE_ITEM: return new RsGxsWirePulseItem(); + default: + return NULL ; + } } void RsGxsWireGroupItem::clear() @@ -48,18 +48,30 @@ void RsGxsWireGroupItem::clear() void RsGxsWireGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) { - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR,group.mDescription,"group.mDescription") ; + RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR,group.mDescription,"group.mDescription") ; } void RsGxsWirePulseItem::clear() { pulse.mPulseText.clear(); - pulse.mHashTags.clear(); + pulse.mPulseType = 0; + pulse.mRefGroupId.clear(); + pulse.mRefGroupName.clear(); + pulse.mRefOrigMsgId.clear(); + pulse.mRefAuthorId.clear(); + pulse.mRefPulseText.clear(); } void RsGxsWirePulseItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) { - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,pulse.mPulseText,"pulse.mPulseText") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_HASH_TAG,pulse.mHashTags,"pulse.mHashTags") ; + RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,pulse.mPulseText,"pulse.mPulseText") ; + RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_UINT32_PARAM,pulse.mPulseType,"pulse.mPulseType") ; + RsTypeSerializer::serial_process(j,ctx,pulse.mRefGroupId,"pulse.mRefGroupId") ; + RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_NAME,pulse.mRefGroupName,"pulse.mRefGroupName") ; + RsTypeSerializer::serial_process(j,ctx,pulse.mRefOrigMsgId,"pulse.mRefOrigMsgId") ; + RsTypeSerializer::serial_process(j,ctx,pulse.mRefAuthorId,"pulse.mRefAuthorId") ; + RsTypeSerializer::serial_process(j,ctx,pulse.mRefPublishTs,"pulse.mRefPublishTs") ; + RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,pulse.mRefPulseText,"pulse.mRefPulseText") ; + } diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index 886660049..5de23251a 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -1381,8 +1381,7 @@ int RsServer::StartupRetroShare() #ifdef RS_USE_WIRE /**** Wire GXS service ****/ RsGeneralDataService* wire_ds = new RsDataService(currGxsDir + "/", "wire_db", - RS_SERVICE_GXS_TYPE_WIRE, - NULL, rsInitConfig->gxs_passwd); + RS_SERVICE_GXS_TYPE_WIRE, NULL, rsInitConfig->gxs_passwd); p3Wire *mWire = new p3Wire(wire_ds, NULL, mGxsIdService); @@ -1826,7 +1825,7 @@ int RsServer::StartupRetroShare() startServiceThread(mPhoto, "gxs photo"); #endif #if RS_USE_WIRE - startServiceThread(mPhoto, "gxs wire"); + startServiceThread(mWire, "gxs wire"); #endif // cores ready start up GXS net servers @@ -1843,7 +1842,7 @@ int RsServer::StartupRetroShare() startServiceThread(photo_ns, "gxs photo ns"); #endif #if RS_USE_WIRE - startServiceThread(photo_ns, "gxs wire ns"); + startServiceThread(wire_ns, "gxs wire ns"); #endif # ifdef RS_GXS_TRANS diff --git a/libretroshare/src/services/p3wire.cc b/libretroshare/src/services/p3wire.cc index 762a8b8af..18119c9a3 100644 --- a/libretroshare/src/services/p3wire.cc +++ b/libretroshare/src/services/p3wire.cc @@ -3,7 +3,7 @@ * * * libretroshare: retroshare core library * * * - * Copyright 2012-2012 by Robert Fernie * + * Copyright 2012-2020 by Robert Fernie * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -83,6 +83,10 @@ void p3Wire::service_tick() return; } +RsTokenService* p3Wire::getTokenService() { + + return RsGenExchange::getTokenService(); +} void p3Wire::notifyChanges(std::vector& changes) { @@ -175,12 +179,12 @@ bool p3Wire::createGroup(uint32_t &token, RsWireGroup &group) groupItem->group = group; groupItem->meta = group.mMeta; - std::cerr << "p3Wire::createGroup(): "; + std::cerr << "p3Wire::createGroup(): "; std::cerr << std::endl; std::cerr << group; std::cerr << std::endl; - std::cerr << "p3Wire::createGroup() pushing to RsGenExchange"; + std::cerr << "p3Wire::createGroup() pushing to RsGenExchange"; std::cerr << std::endl; RsGenExchange::publishGroup(token, groupItem); @@ -193,11 +197,11 @@ bool p3Wire::createPulse(uint32_t &token, RsWirePulse &pulse) std::cerr << "p3Wire::createPulse(): " << pulse; std::cerr << std::endl; - RsGxsWirePulseItem* pulseItem = new RsGxsWirePulseItem(); - pulseItem->pulse = pulse; - pulseItem->meta = pulse.mMeta; + RsGxsWirePulseItem* pulseItem = new RsGxsWirePulseItem(); + pulseItem->pulse = pulse; + pulseItem->meta = pulse.mMeta; - RsGenExchange::publishMsg(token, pulseItem); + RsGenExchange::publishMsg(token, pulseItem); return true; } diff --git a/libretroshare/src/services/p3wire.h b/libretroshare/src/services/p3wire.h index 3858d158e..4a589205b 100644 --- a/libretroshare/src/services/p3wire.h +++ b/libretroshare/src/services/p3wire.h @@ -3,7 +3,7 @@ * * * libretroshare: retroshare core library * * * - * Copyright 2012-2012 by Robert Fernie * + * Copyright 2012-2020 by Robert Fernie * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -34,37 +34,33 @@ * */ - class p3Wire: public RsGenExchange, public RsWire { public: - p3Wire(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs *gixs); -virtual RsServiceInfo getServiceInfo(); -static uint32_t wireAuthenPolicy(); + p3Wire(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs *gixs); + virtual RsServiceInfo getServiceInfo(); + static uint32_t wireAuthenPolicy(); protected: - -virtual void notifyChanges(std::vector& changes) ; + virtual void notifyChanges(std::vector& changes) ; public: + virtual void service_tick(); -virtual void service_tick(); + virtual RsTokenService* getTokenService(); - /* Specific Service Data */ -virtual bool getGroupData(const uint32_t &token, std::vector &groups); -virtual bool getPulseData(const uint32_t &token, std::vector &pulses); + /* Specific Service Data */ + virtual bool getGroupData(const uint32_t &token, std::vector &groups); + virtual bool getPulseData(const uint32_t &token, std::vector &pulses); -virtual bool createGroup(uint32_t &token, RsWireGroup &group); -virtual bool createPulse(uint32_t &token, RsWirePulse &pulse); + virtual bool createGroup(uint32_t &token, RsWireGroup &group); + virtual bool createPulse(uint32_t &token, RsWirePulse &pulse); - private: - -virtual void generateDummyData(); -std::string genRandomId(); +private: + virtual void generateDummyData(); + std::string genRandomId(); RsMutex mWireMtx; - - }; #endif diff --git a/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp b/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp index 94361b8dd..1e0d58ea6 100644 --- a/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp @@ -1,7 +1,7 @@ /******************************************************************************* * gui/TheWire/PulseAddDialog.cpp * * * - * Copyright (c) 2012 Robert Fernie * + * Copyright (c) 2012-2020 Robert Fernie * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Affero General Public License as * @@ -18,39 +18,58 @@ * * *******************************************************************************/ -#include "gui/TheWire/PulseAddDialog.h" - -#include "gui/PhotoShare/PhotoDrop.h" - #include +#include "PulseDetails.h" + +#include "PulseAddDialog.h" + + /** Constructor */ PulseAddDialog::PulseAddDialog(QWidget *parent) -: QWidget(parent) +: QWidget(parent), mIsReply(false), mWaitingRefMsg(false) { ui.setupUi(this); + mWireQueue = new TokenQueue(rsWire->getTokenService(), this); + connect(ui.pushButton_Post, SIGNAL( clicked( void ) ), this, SLOT( postPulse( void ) ) ); connect(ui.pushButton_AddURL, SIGNAL( clicked( void ) ), this, SLOT( addURL( void ) ) ); connect(ui.pushButton_AddTo, SIGNAL( clicked( void ) ), this, SLOT( addTo( void ) ) ); connect(ui.pushButton_Cancel, SIGNAL( clicked( void ) ), this, SLOT( cancelPulse( void ) ) ); -#if 0 - connect(ui.scrollAreaWidgetContents, SIGNAL( buttonStatus( uint32_t ) ), this, SLOT( updateMoveButtons( uint32_t ) ) ); - connect(ui.pushButton_ShiftRight, SIGNAL( clicked( void ) ), ui.scrollAreaWidgetContents, SLOT( moveRight( void ) ) ); - connect(ui.pushButton_EditPhotoDetails, SIGNAL( clicked( void ) ), this, SLOT( showPhotoDetails( void ) ) ); +} - connect(ui.pushButton_Publish, SIGNAL( clicked( void ) ), this, SLOT( publishAlbum( void ) ) ); -#endif +void PulseAddDialog::setGroup(RsWireGroup &group) +{ + ui.label_groupName->setText(QString::fromStdString(group.mMeta.mGroupName)); + ui.label_idName->setText(QString::fromStdString(group.mMeta.mAuthorId.toStdString())); + mGroup = group; +} - mPhotoDetails = NULL; +void PulseAddDialog::setReplyTo(RsWirePulse &pulse, std::string &groupName) +{ + mIsReply = true; + mReplyToPulse = pulse; + mReplyGroupName = groupName; + + { + PulseDetails *details = new PulseDetails(NULL, pulse, groupName, true); + // add extra widget into layout. + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->addWidget(details); + vbox->setSpacing(1); + vbox->setContentsMargins(0,0,0,0); + ui.widget_replyto->setLayout(vbox); + ui.widget_replyto->setVisible(true); + } } void PulseAddDialog::addURL() { - std::cerr << "PulseAddDialog::addURL()"; - std::cerr << std::endl; + std::cerr << "PulseAddDialog::addURL()"; + std::cerr << std::endl; return; } @@ -58,8 +77,8 @@ void PulseAddDialog::addURL() void PulseAddDialog::addTo() { - std::cerr << "PulseAddDialog::addTo()"; - std::cerr << std::endl; + std::cerr << "PulseAddDialog::addTo()"; + std::cerr << std::endl; return; } @@ -67,8 +86,8 @@ void PulseAddDialog::addTo() void PulseAddDialog::cancelPulse() { - std::cerr << "PulseAddDialog::cancelPulse()"; - std::cerr << std::endl; + std::cerr << "PulseAddDialog::cancelPulse()"; + std::cerr << std::endl; clearDialog(); hide(); @@ -77,130 +96,203 @@ void PulseAddDialog::cancelPulse() } - -void PulseAddDialog::updateMoveButtons(uint32_t status) -{ - std::cerr << "PulseAddDialog::updateMoveButtons(" << status << ")"; - std::cerr << std::endl; - -#if 0 - switch(status) - { - case PHOTO_SHIFT_NO_BUTTONS: - ui.pushButton_ShiftLeft->setEnabled(false); - ui.pushButton_ShiftRight->setEnabled(false); - break; - case PHOTO_SHIFT_LEFT_ONLY: - ui.pushButton_ShiftLeft->setEnabled(true); - ui.pushButton_ShiftRight->setEnabled(false); - break; - case PHOTO_SHIFT_RIGHT_ONLY: - ui.pushButton_ShiftLeft->setEnabled(false); - ui.pushButton_ShiftRight->setEnabled(true); - break; - case PHOTO_SHIFT_BOTH: - ui.pushButton_ShiftLeft->setEnabled(true); - ui.pushButton_ShiftRight->setEnabled(true); - break; - } -#endif -} - - -void PulseAddDialog::showPhotoDetails() -{ - -#if 0 - std::cerr << "PulseAddDialog::showPhotoDetails()"; - std::cerr << std::endl; - - if (!mPhotoDetails) - { - mPhotoDetails = new PhotoDetailsDialog(NULL); - } - - PhotoItem *item = ui.scrollAreaWidgetContents->getSelectedPhotoItem(); - - mPhotoDetails->setPhotoItem(item); - mPhotoDetails->show(); -#endif -} - - - - void PulseAddDialog::postPulse() { - std::cerr << "PulseAddDialog::postPulse()"; - std::cerr << std::endl; - -#if 0 - /* we need to iterate through each photoItem, and extract the details */ - - - RsPhotoAlbum album; - RsPhotoThumbnail albumThumb; - - album.mShareOptions.mShareType = 0; - album.mShareOptions.mShareGroupId = "unknown"; - album.mShareOptions.mPublishKey = "unknown"; - album.mShareOptions.mCommentMode = 0; - album.mShareOptions.mResizeMode = 0; - - album.mTitle = ui.lineEdit_Title->text().toStdString(); - album.mCategory = "Unknown"; - album.mCaption = ui.lineEdit_Caption->text().toStdString(); - album.mWhere = ui.lineEdit_Where->text().toStdString(); - album.mWhen = ui.lineEdit_When->text().toStdString(); - - if (rsPhoto->submitAlbumDetails(album, albumThumb)) + std::cerr << "PulseAddDialog::postPulse()"; + std::cerr << std::endl; + if (mIsReply) { - /* now have path and album id */ - int photoCount = ui.scrollAreaWidgetContents->getPhotoCount(); - - for(int i = 0; i < photoCount; ++i) - { - RsPhotoPhoto photo; - RsPhotoThumbnail thumbnail; - PhotoItem *item = ui.scrollAreaWidgetContents->getPhotoIdx(i); - photo = item->mDetails; - item->getPhotoThumbnail(thumbnail); - - photo.mAlbumId = album.mAlbumId; - photo.mOrder = i; - - /* scale photo if needed */ - if (album.mShareOptions.mResizeMode) - { - /* */ - - } - /* save image to album path */ - photo.path = "unknown"; - - rsPhoto->submitPhoto(photo, thumbnail); - } + postReplyPulse(); } + else + { + postOriginalPulse(); + } +} + + +void PulseAddDialog::postOriginalPulse() +{ + std::cerr << "PulseAddDialog::postOriginalPulse()"; + std::cerr << std::endl; + + RsWirePulse pulse; + + pulse.mMeta.mGroupId = mGroup.mMeta.mGroupId; + pulse.mMeta.mAuthorId = mGroup.mMeta.mAuthorId; + pulse.mMeta.mThreadId.clear(); + pulse.mMeta.mParentId.clear(); + pulse.mMeta.mOrigMsgId.clear(); + + pulse.mPulseType = WIRE_PULSE_TYPE_ORIGINAL_MSG; + pulse.mPulseText = ui.textEdit_Pulse->toPlainText().toStdString(); + // all mRefs should empty. + + uint32_t token; + rsWire->createPulse(token, pulse); -#endif clearDialog(); - hide(); } -void PulseAddDialog::clearDialog() +void PulseAddDialog::postReplyPulse() { + std::cerr << "PulseAddDialog::postReplyPulse()"; + std::cerr << std::endl; - ui.textEdit_Pulse->setPlainText(""); -#if 0 - ui.lineEdit_Title->setText(QString("title")); - ui.lineEdit_Caption->setText(QString("Caption")); - ui.lineEdit_Where->setText(QString("Where")); - ui.lineEdit_When->setText(QString("When")); + RsWirePulse pulse; - ui.scrollAreaWidgetContents->clearPhotos(); -#endif + pulse.mMeta.mGroupId = mGroup.mMeta.mGroupId; + pulse.mMeta.mAuthorId = mGroup.mMeta.mAuthorId; + pulse.mMeta.mThreadId.clear(); + pulse.mMeta.mParentId.clear(); + pulse.mMeta.mOrigMsgId.clear(); + + pulse.mPulseType = WIRE_PULSE_TYPE_REPLY_MSG; + pulse.mPulseText = ui.textEdit_Pulse->toPlainText().toStdString(); + + // mRefs refer to parent post. + pulse.mRefGroupId = mReplyToPulse.mMeta.mGroupId; + pulse.mRefGroupName = mReplyGroupName; + pulse.mRefOrigMsgId = mReplyToPulse.mMeta.mOrigMsgId; + pulse.mRefAuthorId = mReplyToPulse.mMeta.mAuthorId; + pulse.mRefPublishTs = mReplyToPulse.mMeta.mPublishTs; + pulse.mRefPulseText = mReplyToPulse.mPulseText; + + // Need Pulse MsgID before we can create associated Reference. + mWaitingRefMsg = true; + + uint32_t token; + rsWire->createPulse(token, pulse); + mWireQueue->queueRequest(token, TOKENREQ_MSGINFO, RS_TOKREQ_ANSTYPE_ACK, 0); } + +void PulseAddDialog::postRefPulse(RsWirePulse &pulse) +{ + std::cerr << "PulseAddDialog::postRefPulse() create Reference!"; + std::cerr << std::endl; + + // Reference Pulse. posted on Parent's Group. + RsWirePulse refPulse; + + refPulse.mMeta.mGroupId = mReplyToPulse.mMeta.mGroupId; + refPulse.mMeta.mAuthorId = mGroup.mMeta.mAuthorId; // own author Id. + refPulse.mMeta.mThreadId = mReplyToPulse.mMeta.mOrigMsgId; + refPulse.mMeta.mParentId = mReplyToPulse.mMeta.mOrigMsgId; + refPulse.mMeta.mOrigMsgId.clear(); + + refPulse.mPulseType = WIRE_PULSE_TYPE_REPLY_REFERENCE; + // Dont put parent PulseText into refPulse - it is available on Thread Msg. + // otherwise gives impression it is correctly setup Parent / Reply... + // when in fact the parent PublishTS, and AuthorId are wrong. + refPulse.mPulseText = ""; + + // refs refer back to own Post. + refPulse.mRefGroupId = mGroup.mMeta.mGroupId; + refPulse.mRefGroupName = mGroup.mMeta.mGroupName; + refPulse.mRefOrigMsgId = pulse.mMeta.mOrigMsgId; + refPulse.mRefAuthorId = mGroup.mMeta.mAuthorId; + refPulse.mRefPublishTs = pulse.mMeta.mPublishTs; + refPulse.mRefPulseText = pulse.mPulseText; + + uint32_t token; + rsWire->createPulse(token, refPulse); + + clearDialog(); + hide(); +} + +void PulseAddDialog::clearDialog() +{ + ui.textEdit_Pulse->setPlainText(""); +} + + +void PulseAddDialog::acknowledgeMessage(const uint32_t &token) +{ + std::cerr << "PulseAddDialog::acknowledgeMessage()"; + std::cerr << std::endl; + + std::pair p; + rsWire->acknowledgeMsg(token, p); + + if (mWaitingRefMsg) + { + std::cerr << "PulseAddDialog::acknowledgeMessage() Waiting Ref Msg"; + std::cerr << std::endl; + mWaitingRefMsg = false; + + // request photo data. + GxsMsgReq req; + std::set msgIds; + msgIds.insert(p.second); + req[p.first] = msgIds; + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + uint32_t token; + mWireQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, req, 0); + } + else + { + std::cerr << "PulseAddDialog::acknowledgeMessage() Not Waiting Ref Msg"; + std::cerr << std::endl; + } +} + +void PulseAddDialog::loadPulseData(const uint32_t &token) +{ + std::cerr << "PulseAddDialog::loadPulseData()"; + std::cerr << std::endl; + std::vector pulses; + rsWire->getPulseData(token, pulses); + + if (pulses.size() != 1) + { + std::cerr << "PulseAddDialog::loadPulseData() Error Too many pulses"; + std::cerr << std::endl; + return; + } + + std::cerr << "PulseAddDialog::loadPulseData() calling postRefMsg"; + std::cerr << std::endl; + + RsWirePulse& pulse = pulses[0]; + postRefPulse(pulse); +} + + +/**************************** Request / Response Filling of Data ************************/ + +void PulseAddDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) +{ + if (queue == mWireQueue) + { + /* now switch on req */ + switch(req.mType) + { + case TOKENREQ_MSGINFO: + switch(req.mAnsType) + { + case RS_TOKREQ_ANSTYPE_ACK: + acknowledgeMessage(req.mToken); + break; + case RS_TOKREQ_ANSTYPE_DATA: + loadPulseData(req.mToken); + break; + default: + std::cerr << "PulseAddDialog::loadRequest() ERROR: MSG: INVALID ANS TYPE"; + std::cerr << std::endl; + break; + } + break; + default: + std::cerr << "PulseAddDialog::loadRequest() ERROR: INVALID TYPE"; + std::cerr << std::endl; + break; + } + } +} diff --git a/retroshare-gui/src/gui/TheWire/PulseAddDialog.h b/retroshare-gui/src/gui/TheWire/PulseAddDialog.h index 79c82128f..e48ecfeea 100644 --- a/retroshare-gui/src/gui/TheWire/PulseAddDialog.h +++ b/retroshare-gui/src/gui/TheWire/PulseAddDialog.h @@ -1,7 +1,7 @@ /******************************************************************************* * gui/TheWire/PulseAddDialog.h * * * - * Copyright (c) 2012 Robert Fernie * + * Copyright (c) 2012-2020 Robert Fernie * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Affero General Public License as * @@ -23,30 +23,46 @@ #include "ui_PulseAddDialog.h" -#include +#include +#include "util/TokenQueue.h" -class PhotoDetailsDialog; - -class PulseAddDialog : public QWidget +class PulseAddDialog : public QWidget, public TokenResponse { Q_OBJECT public: PulseAddDialog(QWidget *parent = 0); -private slots: - void showPhotoDetails(); - void updateMoveButtons(uint32_t status); + void setGroup(RsWireGroup &group); + void setReplyTo(RsWirePulse &pulse, std::string &groupName); +private slots: void addURL(); void addTo(); void postPulse(); void cancelPulse(); void clearDialog(); +private: + void postOriginalPulse(); + void postReplyPulse(); + void postRefPulse(RsWirePulse &pulse); + + void acknowledgeMessage(const uint32_t &token); + void loadPulseData(const uint32_t &token); + void loadRequest(const TokenQueue *queue, const TokenRequest &req); + protected: - PhotoDetailsDialog *mPhotoDetails; + RsWireGroup mGroup; // where we want to post from. + + // if this is a reply + bool mIsReply; + std::string mReplyGroupName; + RsWirePulse mReplyToPulse; + bool mWaitingRefMsg; + + TokenQueue* mWireQueue; Ui::PulseAddDialog ui; }; diff --git a/retroshare-gui/src/gui/TheWire/PulseAddDialog.ui b/retroshare-gui/src/gui/TheWire/PulseAddDialog.ui index 08110c603..cdcbf632c 100644 --- a/retroshare-gui/src/gui/TheWire/PulseAddDialog.ui +++ b/retroshare-gui/src/gui/TheWire/PulseAddDialog.ui @@ -14,196 +14,75 @@ - - - - Qt::Vertical + + + + QFrame::StyledPanel - - - - 160 - 16777215 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 0 - - - 0 - - - - - - 0 - 0 - - - - true - - - - - 0 - 0 - 156 - 184 - - - - - - - - 12 - 75 - true - - - - Post From: - - - - - - - Account 1 - - - - - - - Account 2 - - - - - - - Account 3 - - - - - - - Qt::Vertical - - - - 20 - 0 - - - - - - - - - - - - - true - - - - - 0 - 0 - 158 - 372 - - - + + QFrame::Raised + + + + - + - Add to Pulse + In Reply to: - + + + + 11 + 75 + true + + - filter + Positive / Neutral / Negative - - - true + + + Qt::Horizontal - - - - 0 - 0 - 138 - 286 - - - - - - - Account 1 - - - - - - - Account 2 - - - - - - - Account 3 - - - - - - - Qt::Vertical - - - - 20 - 70 - - - - - - - + + + 238 + 20 + + + - - + + + + + - - - + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + URL Adder @@ -252,14 +131,14 @@ - + Cancel - + Qt::Horizontal @@ -272,17 +151,159 @@ - + Post Pulse to Wire + + + + Qt::Vertical + + + + + 160 + 16777215 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 12 + 75 + true + + + + Post From: + + + + + + + GroupLabel + + + + + + + IDLabel + + + + + + + + true + + + + + 0 + 0 + 150 + 423 + + + + + + + Add to Pulse + + + + + + + filter + + + + + + + true + + + + + 0 + 0 + 130 + 341 + + + + + + + Account 1 + + + + + + + Account 2 + + + + + + + Account 3 + + + + + + + Qt::Vertical + + + + 20 + 70 + + + + + + + + + + + + + + + + GxsIdLabel + QLabel +
gui/gxs/GxsIdLabel.h
+
+
- + diff --git a/retroshare-gui/src/gui/TheWire/PulseDetails.cpp b/retroshare-gui/src/gui/TheWire/PulseDetails.cpp new file mode 100644 index 000000000..7bb1f2615 --- /dev/null +++ b/retroshare-gui/src/gui/TheWire/PulseDetails.cpp @@ -0,0 +1,144 @@ +/******************************************************************************* + * gui/TheWire/PulseDetails.cpp * + * * + * Copyright (c) 2020 Robert Fernie * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +#include +#include +#include +#include + +#include "PulseDetails.h" + +#include "util/DateTime.h" + +#include +#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) +{ + setupUi(this); + setAttribute ( Qt::WA_DeleteOnClose, true ); + setup(); +} + +PulseDetails::PulseDetails(PulseHolder *actions, + RsGxsGroupId &parentGroupId, + std::string &parentGroupName, + RsGxsMessageId &parentOrigMsgId, + RsGxsId &parentAuthorId, + rstime_t &parentPublishTs, + std::string &parentPulseText) +:QWidget(NULL), mActions(actions), mPulse(), mGroupName(parentGroupName), mIsOriginal(false) +{ + setupUi(this); + setAttribute ( Qt::WA_DeleteOnClose, true ); + + // reuse Meta data structure. + mPulse.mMeta.mGroupId = parentGroupId; + mPulse.mMeta.mOrigMsgId = parentOrigMsgId; + mPulse.mMeta.mAuthorId = parentAuthorId; + mPulse.mMeta.mPublishTs = parentPublishTs; + mPulse.mPulseText = parentPulseText; + setup(); +} + +void PulseDetails::setup() +{ + connect(toolButton_expand, SIGNAL(clicked()), this, SLOT(toggle())); + + connect(toolButton_follow, SIGNAL(clicked()), this, SLOT(follow())); + connect(toolButton_rate, SIGNAL(clicked()), this, SLOT(rate())); + connect(toolButton_reply, SIGNAL(clicked()), this, SLOT(reply())); + + label_wireName->setText(QString::fromStdString(mGroupName)); + label_idName->setId(mPulse.mMeta.mAuthorId); + + label_date->setText(DateTime::formatDateTime(mPulse.mMeta.mPublishTs)); + label_summary->setText(getSummary()); + + // label_icon->setText(); + textBrowser->setPlainText(QString::fromStdString(mPulse.mPulseText)); + frame_expand->setVisible(false); +} + + +void PulseDetails::toggle() +{ + if (frame_expand->isVisible()) { + // switch to minimal view. + label_summary->setVisible(true); + frame_expand->setVisible(false); + } else { + // switch to expanded view. + label_summary->setVisible(false); + frame_expand->setVisible(true); + } +} + +QString PulseDetails::getSummary() +{ + std::string summary = mPulse.mPulseText; + std::cerr << "PulseDetails::getSummary() orig: " << summary; + std::cerr << std::endl; + int len = summary.size(); + bool in_whitespace = false; + for (int i = 0; i < len; i++) + { + if (isspace(summary[i])) { + if (in_whitespace) { + // trim + summary.erase(i, 1); + // rollback index / len. + --i; + --len; + } else { + // replace whitespace with space. + summary[i] = ' '; + in_whitespace = true; + } + } else { + in_whitespace = false; + } + } + std::cerr << "PulseDetails::getSummary() summary: " << summary; + std::cerr << std::endl; + + return QString::fromStdString(summary); +} + +void PulseDetails::follow() +{ + // follow group. + mActions->follow(mPulse.mMeta.mGroupId); +} + +void PulseDetails::rate() +{ + // rate author + mActions->rate(mPulse.mMeta.mAuthorId); +} + +void PulseDetails::reply() +{ + mActions->reply(mPulse, mGroupName); +} + + diff --git a/retroshare-gui/src/gui/TheWire/PulseDetails.h b/retroshare-gui/src/gui/TheWire/PulseDetails.h new file mode 100644 index 000000000..6b063eab9 --- /dev/null +++ b/retroshare-gui/src/gui/TheWire/PulseDetails.h @@ -0,0 +1,62 @@ +/******************************************************************************* + * gui/TheWire/PulseDetails.h * + * * + * Copyright (c) 2020 Robert Fernie * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +#ifndef MRK_PULSE_DETAILS_H +#define MRK_PULSE_DETAILS_H + +#include "ui_PulseDetails.h" +#include "PulseItem.h" + +#include + +class PulseDetails : public QWidget, private Ui::PulseDetails +{ + Q_OBJECT + +public: + PulseDetails(PulseHolder *actions, RsWirePulse &pulse, std::string &groupName, bool is_original); + + // when Reply parent.... + PulseDetails(PulseHolder *actions, + RsGxsGroupId &parentGroupId, + std::string &parentGroupName, + RsGxsMessageId &parentOrigMsgId, + RsGxsId &parentAuthorId, + rstime_t &parentPublishTs, + std::string &parentPulseText); + + void setup(); + +private slots: + void toggle(); + void follow(); + void rate(); + void reply(); + +private: + QString getSummary(); + + PulseHolder *mActions; + RsWirePulse mPulse; + std::string mGroupName; + bool mIsOriginal; +}; + +#endif diff --git a/retroshare-gui/src/gui/TheWire/PulseDetails.ui b/retroshare-gui/src/gui/TheWire/PulseDetails.ui new file mode 100644 index 000000000..3739dd0da --- /dev/null +++ b/retroshare-gui/src/gui/TheWire/PulseDetails.ui @@ -0,0 +1,185 @@ + + + PulseDetails + + + + 0 + 0 + 750 + 166 + + + + Form + + + + + + + + \/ + + + + + + + WireGroupName + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 20 + 20 + + + + + + + + idLabel + + + + + + + Qt::Horizontal + + + + 128 + 20 + + + + + + + + Summary Text/ date + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 20 + 20 + + + + + + + + TextLabel + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + follow + + + + + + + reply + + + + + + + rate + + + + + + + + + + + + 80 + 80 + + + + Image + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 5 + + + + + + + + + + + + + + + + + GxsIdLabel + QLabel +
gui/gxs/GxsIdLabel.h
+
+
+ + +
diff --git a/retroshare-gui/src/gui/TheWire/PulseItem.cpp b/retroshare-gui/src/gui/TheWire/PulseItem.cpp index 16b01d3a4..3b452ffdf 100644 --- a/retroshare-gui/src/gui/TheWire/PulseItem.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseItem.cpp @@ -1,7 +1,7 @@ /******************************************************************************* * gui/TheWire/PulseItem.cpp * * * - * Copyright (c) 2012 Robert Fernie * + * Copyright (c) 2012-2020 Robert Fernie * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Affero General Public License as * @@ -25,6 +25,8 @@ #include "PulseItem.h" +#include "PulseDetails.h" + #include #include @@ -34,14 +36,119 @@ /** Constructor */ -PulseItem::PulseItem(PulseHolder *parent, std::string path) -:QWidget(NULL), mParent(parent), mType(0) +PulseItem::PulseItem(PulseHolder *holder, std::string path) +:QWidget(NULL), mHolder(holder), mType(0) { - setupUi(this); - setAttribute ( Qt::WA_DeleteOnClose, true ); + setupUi(this); + setAttribute ( Qt::WA_DeleteOnClose, true ); } +PulseItem::PulseItem(PulseHolder *holder, RsWirePulse &pulse, RsWireGroup &group) +:QWidget(NULL), mHolder(holder), 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) { + + std::cerr << "Installing Reply 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_parent->setLayout(vbox); + + // if its a reply, the real msg goes into reply slot. + pulse_widget = widget_reply; + } + else if (pulse.mPulseType & WIRE_PULSE_TYPE_REPLY_REFERENCE) + { + // 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); + } + + { + std::cerr << "Adding Main Message"; + std::cerr << std::endl; + PulseDetails *details = new PulseDetails(mHolder, pulse, group.mMeta.mGroupName, true); + + // add extra widget into layout. + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->addWidget(details); + vbox->setSpacing(1); + vbox->setContentsMargins(0,0,0,0); + pulse_widget->setLayout(vbox); + pulse_widget->setVisible(true); + // details->toggle(); + } +} + + void PulseItem::removeItem() { } @@ -52,29 +159,29 @@ void PulseItem::setSelected(bool on) bool PulseItem::isSelected() { - return mSelected; + return mSelected; } void PulseItem::mousePressEvent(QMouseEvent *event) { - /* We can be very cunning here? - * grab out position. - * flag ourselves as selected. - * then pass the mousePressEvent up for handling by the parent - */ + /* We can be very cunning here? + * grab out position. + * flag ourselves as selected. + * then pass the mousePressEvent up for handling by the parent + */ - QPoint pos = event->pos(); + QPoint pos = event->pos(); - std::cerr << "PulseItem::mousePressEvent(" << pos.x() << ", " << pos.y() << ")"; - std::cerr << std::endl; + std::cerr << "PulseItem::mousePressEvent(" << pos.x() << ", " << pos.y() << ")"; + std::cerr << std::endl; - setSelected(true); + setSelected(true); - QWidget::mousePressEvent(event); + QWidget::mousePressEvent(event); } const QPixmap *PulseItem::getPixmap() { - return NULL; + return NULL; } diff --git a/retroshare-gui/src/gui/TheWire/PulseItem.h b/retroshare-gui/src/gui/TheWire/PulseItem.h index 6bfeb3506..03ac190fb 100644 --- a/retroshare-gui/src/gui/TheWire/PulseItem.h +++ b/retroshare-gui/src/gui/TheWire/PulseItem.h @@ -1,7 +1,7 @@ /******************************************************************************* * gui/TheWire/PulseItem.h * * * - * Copyright (c) 2012 Robert Fernie * + * Copyright (c) 2012-2020 Robert Fernie * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Affero General Public License as * @@ -23,37 +23,48 @@ #include "ui_PulseItem.h" +#include + class PulseItem; class PulseHolder { - public: -virtual void deletePulseItem(PulseItem *, uint32_t ptype) = 0; -virtual void notifySelection(PulseItem *item, int ptype) = 0; +public: + virtual ~PulseHolder() {} + virtual void deletePulseItem(PulseItem *, uint32_t ptype) = 0; + virtual void notifySelection(PulseItem *item, int ptype) = 0; + + // Actions. + virtual void follow(RsGxsGroupId &groupId) = 0; + virtual void rate(RsGxsId &authorId) = 0; + virtual void reply(RsWirePulse &pulse, std::string &groupName) = 0; }; + class PulseItem : public QWidget, private Ui::PulseItem { Q_OBJECT public: - PulseItem(PulseHolder *parent, std::string url); + PulseItem(PulseHolder *holder, std::string url); + PulseItem(PulseHolder *holder, RsWirePulse &pulse, RsWireGroup &group); - void removeItem(); + void removeItem(); - void setSelected(bool on); - bool isSelected(); + void setSelected(bool on); + bool isSelected(); - const QPixmap *getPixmap(); + const QPixmap *getPixmap(); protected: - void mousePressEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); private: - PulseHolder *mParent; - uint32_t mType; - bool mSelected; + PulseHolder *mHolder; + RsWirePulse mPulse; + uint32_t mType; + bool mSelected; }; #endif diff --git a/retroshare-gui/src/gui/TheWire/PulseItem.ui b/retroshare-gui/src/gui/TheWire/PulseItem.ui index 6a0286af8..c032446a8 100644 --- a/retroshare-gui/src/gui/TheWire/PulseItem.ui +++ b/retroshare-gui/src/gui/TheWire/PulseItem.ui @@ -6,10 +6,16 @@ 0 0 - 615 - 232 + 802 + 322 + + + 0 + 0 + + 9 @@ -18,7 +24,7 @@ - + @@ -27,6 +33,12 @@ 0 + + + 0 + 0 + + QFrame#frame{border: 2px solid #CCCCCC; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, @@ -39,164 +51,103 @@ border-radius: 10px} QFrame::Raised - - - - - - 75 - 75 - - - - - 75 - 75 - - - - QLabel#label{border: 2px solid black; -background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #EEEEEE, stop: 1 #CCCCCC); -border-radius: 10px} - - - - - - :/images/konversation.png - - - Qt::AlignCenter - - - - - - - - - - 0 - 0 - - - - - 9 - 75 - true - - - - From - - - - - - - - 0 - 0 - - - - - 9 - - - - Signed by - - - true - - - - - - - - - - - - 0 - 0 - - - - - 9 - 75 - true - - - - Date - - - - - - - - 0 - 0 - - - - - 9 - - - - You eyes only - - - true - - - - - - - - - - - - Qt::Vertical - - - - 48 - 75 - - - - - + + - - - ... + + + + 20 + 0 + + + + + 0 + 0 + + + + QFrame::StyledPanel - - - ... + + + Qt::Vertical - + + + 10 + 40 + + + - - - ... + + + Qt::Horizontal + + + + 50 + 20 + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 50 + 20 + + + + + + + + Qt::Vertical + + + + 10 + 40 + + + + + + + + + 20 + 0 + + + + + 0 + 0 + + + + QFrame::StyledPanel @@ -208,7 +159,7 @@ border-radius: 10px}
- + diff --git a/retroshare-gui/src/gui/TheWire/TheWire_images.qrc b/retroshare-gui/src/gui/TheWire/TheWire_images.qrc new file mode 100644 index 000000000..7919a4500 --- /dev/null +++ b/retroshare-gui/src/gui/TheWire/TheWire_images.qrc @@ -0,0 +1,15 @@ + + + images/kuickshow.png + images/kview_24.png + images/kview_64.png + images/album_64.png + images/album_subscribe.png + images/album_unsubscribe.png + images/album_create_64.png + images/album_default_128.png + images/my_album_48.png + images/subscribed_album_48.png + images/friends_album_48.png + + diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.cpp b/retroshare-gui/src/gui/TheWire/WireDialog.cpp index 90ce66ea1..7dd1e1199 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/WireDialog.cpp @@ -1,7 +1,7 @@ /******************************************************************************* * gui/TheWire/WireDialog.cpp * * * - * Copyright (c) 2012 Robert Fernie * + * Copyright (c) 2012-2020 Robert Fernie * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Affero General Public License as * @@ -20,40 +20,24 @@ #include "WireDialog.h" +#include "WireGroupDialog.h" +#include "WireGroupItem.h" + #include -#include +#include #include #include #include - -/****** - * #define PHOTO_DEBUG 1 - *****/ - +#include /**************************************************************** - * New Photo Display Widget. + * TheWire Display Widget. * - * This has two 'lists'. - * Top list shows Albums. - * Lower list is photos from the selected Album. - * - * Notes: - * Each Item will be an AlbumItem, which contains a thumbnail & random details. - * We will limit Items to < 100. With a 'Filter to see more message. - * - * Thumbnails will come from Service. - * Option to Share albums / pictures onward (if permissions allow). - * Option to Download the albums to a specified directory. (is this required if sharing an album?) - * - * Will introduce a FullScreen SlideShow later... first get basics happening. */ - - /** Constructor */ WireDialog::WireDialog(QWidget *parent) : MainPage(parent) @@ -63,36 +47,103 @@ WireDialog::WireDialog(QWidget *parent) mAddDialog = NULL; mPulseSelected = NULL; - connect( ui.pushButton_Post, SIGNAL(clicked()), this, SLOT(OpenOrShowPulseAddDialog())); - //connect( ui.pushButton_Accounts, SIGNAL(clicked()), this, SLOT(OpenOrShowAccountDialog())); + connect( ui.toolButton_createAccount, SIGNAL(clicked()), this, SLOT(createGroup())); + connect( ui.toolButton_createPulse, SIGNAL(clicked()), this, SLOT(createPulse())); + connect( ui.pushButton_Post, SIGNAL(clicked()), this, SLOT(createPulse())); + connect( ui.toolButton_refresh, SIGNAL(clicked()), this, SLOT(refreshGroups())); QTimer *timer = new QTimer(this); timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); timer->start(1000); + /* setup TokenQueue */ + mWireQueue = new TokenQueue(rsWire->getTokenService(), this); + requestGroupData(); +} + +void WireDialog::refreshGroups() +{ + requestGroupData(); +} + +void WireDialog::addItem(QWidget *item) +{ + QLayout *alayout = ui.scrollAreaWidgetContents->layout(); + alayout->addWidget(item); } +void WireDialog::addGroup(QWidget *item) +{ + QLayout *alayout = ui.scrollAreaWidgetContents_groups->layout(); + alayout->addWidget(item); +} + +// PulseHolder interface. +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; + std::cerr << "WireDialog::notifySelection() from : " << ptype << " " << item; + std::cerr << std::endl; notifyPulseSelection(item); +} -#if 0 - switch(ptype) + + // Actions from PulseHolder. +void WireDialog::follow(RsGxsGroupId &groupId) +{ + std::cerr << "WireDialog::follow("; + std::cerr << groupId.toStdString(); + std::cerr << ")"; + std::cerr << std::endl; +} + +void WireDialog::rate(RsGxsId &authorId) +{ + std::cerr << "WireDialog::rate("; + std::cerr << authorId.toStdString(); + std::cerr << ")"; + std::cerr << std::endl; +} + +void WireDialog::reply(RsWirePulse &pulse, std::string &groupName) +{ + std::cerr << "WireDialog::reply("; + std::cerr << pulse.mMeta.mGroupId.toStdString(); + std::cerr << ","; + std::cerr << pulse.mMeta.mOrigMsgId.toStdString(); + std::cerr << ")"; + std::cerr << std::endl; + + if (!mAddDialog) { - default: - case PHOTO_ITEM_TYPE_ALBUM: - notifyAlbumSelection(item); - break; - case PHOTO_ITEM_TYPE_PHOTO: - notifyPhotoSelection(item); - break; + mAddDialog = new PulseAddDialog(NULL); + mAddDialog->hide(); } -#endif + + int idx = ui.groupChooser->currentIndex(); + if (idx < 0) { + std::cerr << "WireDialog::reply() ERROR GETTING AuthorId!"; + std::cerr << std::endl; + + QMessageBox::warning(this, tr("RetroShare"),tr("Please create or choose Wire Groupd first"), QMessageBox::Ok, QMessageBox::Ok); + return; + } + + // publishing group. + RsWireGroup group = mOwnGroups[idx]; + mAddDialog->setGroup(group); + + // establish replyTo. + mAddDialog->setReplyTo(pulse, groupName); + + mAddDialog->show(); } void WireDialog::notifyPulseSelection(PulseItem *item) @@ -127,331 +178,305 @@ void WireDialog::checkUpdate() return; } - -/*************** New Photo Dialog ***************/ - -void WireDialog::OpenOrShowPulseAddDialog() +void WireDialog::createGroup() { - if (mAddDialog) - { - mAddDialog->show(); - } - else + WireGroupDialog wireCreate(mWireQueue, this); + wireCreate.exec(); +} + +void WireDialog::createPulse() +{ + if (!mAddDialog) { mAddDialog = new PulseAddDialog(NULL); - mAddDialog->show(); - } -} - - -bool WireDialog::matchesAlbumFilter(const RsPhotoAlbum &album) -{ - - return true; -} - -double WireDialog::AlbumScore(const RsPhotoAlbum &album) -{ - return 1; -} - - -bool WireDialog::matchesPhotoFilter(const RsPhotoPhoto &photo) -{ - - return true; -} - -double WireDialog::PhotoScore(const RsPhotoPhoto &photo) -{ - return 1; -} - - -bool WireDialog::FilterNSortAlbums(const std::list &albumIds, std::list &filteredAlbumIds, int count) -{ -#if 0 - std::multimap sortedAlbums; - std::multimap::iterator sit; - std::list::const_iterator it; - - for(it = albumIds.begin(); it != albumIds.end(); ++it) - { - RsPhotoAlbum album; - rsPhoto->getAlbum(*it, album); - - if (matchesAlbumFilter(album)) - { - double score = AlbumScore(album); - - sortedAlbums.insert(std::make_pair(score, *it)); - } + mAddDialog->hide(); } - int i; - for (sit = sortedAlbums.begin(), i = 0; (sit != sortedAlbums.end()) && (i < count); ++sit, ++i) - { - filteredAlbumIds.push_back(sit->second); - } -#endif - return true; -} - - -bool WireDialog::FilterNSortPhotos(const std::list &photoIds, std::list &filteredPhotoIds, int count) -{ -#if 0 - std::multimap sortedPhotos; - std::multimap::iterator sit; - std::list::const_iterator it; - - int i = 0; - for(it = photoIds.begin(); it != photoIds.end(); ++it, ++i) - { - RsPhotoPhoto photo; - rsPhoto->getPhoto(*it, photo); - - if (matchesPhotoFilter(photo)) - { - double score = i; //PhotoScore(album); - sortedPhotos.insert(std::make_pair(score, *it)); - } - } - - for (sit = sortedPhotos.begin(), i = 0; (sit != sortedPhotos.end()) && (i < count); ++sit, ++i) - { - filteredPhotoIds.push_back(sit->second); - } -#endif - return true; -} - - - -void WireDialog::insertAlbums() -{ -#if 0 - /* clear it all */ - clearAlbums(); - //ui.albumLayout->clear(); - - /* create a list of albums */ - - - std::list albumIds; - std::list filteredAlbumIds; - std::list::iterator it; - - rsPhoto->getAlbumList(albumIds); - - /* Filter Albums */ /* Sort Albums */ -#define MAX_ALBUMS 50 - - int count = MAX_ALBUMS; - FilterNSortAlbums(albumIds, filteredAlbumIds, count); - - for(it = filteredAlbumIds.begin(); it != filteredAlbumIds.end(); ++it) - { - addAlbum(*it); - } - - insertPhotosForAlbum(filteredAlbumIds); -#endif -} - -void WireDialog::insertPhotosForSelectedAlbum() -{ -#if 0 - std::cerr << "WireDialog::insertPhotosForSelectedAlbum()"; - std::cerr << std::endl; - - clearPhotos(); - - std::list albumIds; - if (mAlbumSelected) - { - albumIds.push_back(mAlbumSelected->mDetails.mAlbumId); - - std::cerr << "WireDialog::insertPhotosForSelectedAlbum() AlbumId: " << mAlbumSelected->mDetails.mAlbumId; + int idx = ui.groupChooser->currentIndex(); + if (idx < 0) { + std::cerr << "WireDialog::createPulse() ERROR GETTING AuthorId!"; std::cerr << std::endl; + + QMessageBox::warning(this, tr("RetroShare"),tr("Please create or choose Wire Groupd first"), QMessageBox::Ok, QMessageBox::Ok); + return; } - insertPhotosForAlbum(albumIds); -#endif + RsWireGroup group = mOwnGroups[idx]; + + mAddDialog->setGroup(group); + mAddDialog->show(); } - -void WireDialog::addAlbum(const std::string &id) +void WireDialog::addPulse(RsWirePulse &pulse, RsWireGroup &group) { -#if 0 - RsPhotoAlbum album; - rsPhoto->getAlbum(id, album); - - - RsPhotoThumbnail thumbnail; - rsPhoto->getAlbumThumbnail(id, thumbnail); - - std::cerr << " WireDialog::addAlbum() AlbumId: " << album.mAlbumId << std::endl; - - PulseItem *item = new PulseItem(this, album, thumbnail); - QLayout *alayout = ui.scrollAreaWidgetContents->layout(); - alayout->addWidget(item); -#endif -} - -void WireDialog::clearAlbums() -{ -#if 0 - std::cerr << "WireDialog::clearAlbums()" << std::endl; - - std::list photoItems; - std::list::iterator pit; - - QLayout *alayout = ui.scrollAreaWidgetContents->layout(); - int count = alayout->count(); - for(int i = 0; i < count; ++i) - { - QLayoutItem *litem = alayout->itemAt(i); - if (!litem) - { - std::cerr << "WireDialog::clearAlbums() missing litem"; - std::cerr << std::endl; - continue; - } - - PulseItem *item = dynamic_cast(litem->widget()); - if (item) - { - std::cerr << "WireDialog::clearAlbums() item: " << item; - std::cerr << std::endl; - - photoItems.push_back(item); - } - else - { - std::cerr << "WireDialog::clearAlbums() Found Child, which is not a PulseItem???"; - std::cerr << std::endl; - } - } - - for(pit = photoItems.begin(); pit != photoItems.end(); ++pit) - { - PulseItem *item = *pit; - alayout->removeWidget(item); - delete item; - } - mAlbumSelected = NULL; -#endif -} - -void WireDialog::clearPhotos() -{ -#if 0 - std::cerr << "WireDialog::clearPhotos()" << std::endl; - - std::list photoItems; - std::list::iterator pit; - - QLayout *alayout = ui.scrollAreaWidgetContents_2->layout(); - int count = alayout->count(); - for(int i = 0; i < count; ++i) - { - QLayoutItem *litem = alayout->itemAt(i); - if (!litem) - { - std::cerr << "WireDialog::clearPhotos() missing litem"; - std::cerr << std::endl; - continue; - } - - PulseItem *item = dynamic_cast(litem->widget()); - if (item) - { - std::cerr << "WireDialog::clearPhotos() item: " << item; - std::cerr << std::endl; - - photoItems.push_back(item); - } - else - { - std::cerr << "WireDialog::clearPhotos() Found Child, which is not a PulseItem???"; - std::cerr << std::endl; - } - } - - for(pit = photoItems.begin(); pit != photoItems.end(); ++pit) - { - PulseItem *item = *pit; - alayout->removeWidget(item); - delete item; - } - - mPhotoSelected = NULL; -#endif - -} - - -void WireDialog::insertPhotosForAlbum(const std::list &albumIds) -{ -#if 0 - /* clear it all */ - clearPhotos(); - //ui.photoLayout->clear(); - - /* create a list of albums */ - - std::list ids; - std::list photoIds; - std::list filteredPhotoIds; - std::list::const_iterator it; - - for(it = albumIds.begin(); it != albumIds.end(); ++it) - { - rsPhoto->getPhotoList(*it, photoIds); - } - - /* Filter Albums */ /* Sort Albums */ -#define MAX_PHOTOS 50 - - int count = MAX_PHOTOS; - - FilterNSortPhotos(photoIds, filteredPhotoIds, MAX_PHOTOS); - - for(it = filteredPhotoIds.begin(); it != filteredPhotoIds.end(); ++it) - { - addPhoto(*it); - } -#endif -} - - -void WireDialog::addPhoto(const std::string &id) -{ -#if 0 - RsPhotoPhoto photo; - rsPhoto->getPhoto(id,photo); - - RsPhotoThumbnail thumbnail; - rsPhoto->getPhotoThumbnail(id, thumbnail); - - std::cerr << "WireDialog::addPhoto() AlbumId: " << photo.mAlbumId; - std::cerr << " PhotoId: " << photo.mId; + std::cerr << "WireDialog::addPulse() GroupId : " << pulse.mMeta.mGroupId; + std::cerr << " MsgId : " << pulse.mMeta.mGroupId; std::cerr << std::endl; - PulseItem *item = new PulseItem(this, photo, thumbnail); - QLayout *alayout = ui.scrollAreaWidgetContents_2->layout(); - alayout->addWidget(item); -#endif + QWidget *item = new PulseItem(this, pulse, group); + addItem(item); } - -void WireDialog::deletePulseItem(PulseItem *item, uint32_t type) +void WireDialog::addGroup(RsWireGroup &group) { + std::cerr << "WireDialog::addGroup() GroupId : " << group.mMeta.mGroupId; + std::cerr << std::endl; + + addGroup(new WireGroupItem(group)); +} + +void WireDialog::deletePulses() +{ + std::cerr << "WireDialog::deletePulses()"; + std::cerr << std::endl; + + QLayout *alayout = ui.scrollAreaWidgetContents->layout(); + QLayoutItem *item; + int i = 0; + while (i < alayout->count()) + { + item = alayout->itemAt(i); + QWidget *widget = item->widget(); + if (NULL != dynamic_cast(widget)) + { + std::cerr << "WireDialog::deletePulses() Removing Item at: " << i; + std::cerr << std::endl; + + item = alayout->takeAt(i); + delete item->widget(); + delete item; + } + else + { + std::cerr << "WireDialog::deletePulses() Leaving Item at: " << i; + std::cerr << std::endl; + + i++; + } + } +} + +void WireDialog::deleteGroups() +{ + std::cerr << "WireDialog::deleteGroups()"; + std::cerr << std::endl; + + mAllGroups.clear(); + mOwnGroups.clear(); + ui.groupChooser->clear(); - return; + QLayout *alayout = ui.scrollAreaWidgetContents_groups->layout(); + QLayoutItem *item; + int i = 0; + while (i < alayout->count()) + { + item = alayout->itemAt(i); + QWidget *widget = item->widget(); + if (NULL != dynamic_cast(widget)) + { + std::cerr << "WireDialog::deleteGroups() Removing Item at: " << i; + std::cerr << std::endl; + + item = alayout->takeAt(i); + delete item->widget(); + delete item; + } + else + { + std::cerr << "WireDialog::deleteGroups() Leaving Item at: " << i; + std::cerr << std::endl; + + i++; + } + } +} + +void WireDialog::updateGroups(std::vector& groups) +{ + std::vector::const_iterator it; + for(it = groups.begin(); it != groups.end(); it++) { + // save list of all groups. + mAllGroups[it->mMeta.mGroupId] = *it; + + if (it->mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) + { + // grab own groups. + // setup Chooser too. + mOwnGroups.push_back(*it); + ui.groupChooser->addItem(QString::fromStdString(it->mMeta.mGroupName)); + } + } } +// LOAD DATA............................................... + + +void WireDialog::requestGroupData() +{ + std::cerr << "WireDialog::requestGroupData()"; + std::cerr << std::endl; + + RsTokReqOptions opts; + uint32_t token; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + mWireQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, 0); +} + +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); + return true; +} + +void WireDialog::requestPulseData(const std::list& grpIds) +{ + std::cerr << "WireDialog::requestPulseData()"; + std::cerr << std::endl; + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + opts.mOptions = RS_TOKREQOPT_MSG_LATEST; + uint32_t token; + mWireQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds, 0); +} + +bool WireDialog::loadPulseData(const uint32_t &token) +{ + std::cerr << "WireDialog::loadPulseData()"; + std::cerr << std::endl; + + // clearPulses(); + + std::vector pulses; + rsWire->getPulseData(token, pulses); + + 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()) + { + RsWireGroup &group = mit->second; + addPulse(pulse, group); + std::cerr << "WireDialog::loadPulseData() GroupId: " << pulse.mMeta.mGroupId; + std::cerr << " PulseId: " << pulse.mMeta.mMsgId; + std::cerr << std::endl; + } + else + { + std::cerr << "WireDialog::loadPulseData() ERROR Missing GroupId: " << pulse.mMeta.mGroupId; + std::cerr << " PulseId: " << pulse.mMeta.mMsgId; + std::cerr << std::endl; + } + } + + // updatePulses(); + return true; +} + + +/**************************** Request / Response Filling of Data ************************/ + +void WireDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) +{ + std::cerr << "WireDialog::loadRequest()"; + std::cerr << std::endl; + + if (queue == mWireQueue) + { + /* now switch on req */ + switch(req.mType) + { + case TOKENREQ_GROUPINFO: + switch(req.mAnsType) + { + // case RS_TOKREQ_ANSTYPE_LIST: + // loadGroupList(req.mToken); + // break; + case RS_TOKREQ_ANSTYPE_DATA: + loadGroupData(req.mToken); + break; + // case RS_TOKREQ_ANSTYPE_ACK: + // acknowledgeGroup(req.mToken); + // break; + default: + std::cerr << "WireDialog::loadRequest() ERROR: GROUP: INVALID ANS TYPE"; + std::cerr << std::endl; + break; + } + break; + case TOKENREQ_MSGINFO: + switch(req.mAnsType) + { +#if 0 + case RS_TOKREQ_ANSTYPE_LIST: + loadPhotoList(req.mToken); + break; + case RS_TOKREQ_ANSTYPE_ACK: + acknowledgeMessage(req.mToken); + break; +#endif + case RS_TOKREQ_ANSTYPE_DATA: + loadPulseData(req.mToken); + break; + default: + std::cerr << "WireDialog::loadRequest() ERROR: MSG: INVALID ANS TYPE"; + std::cerr << std::endl; + break; + } + break; +#if 0 + case TOKENREQ_MSGRELATEDINFO: + switch(req.mAnsType) + { + case RS_TOKREQ_ANSTYPE_DATA: + loadPhotoData(req.mToken); + break; + default: + std::cerr << "WireDialog::loadRequest() ERROR: MSG: INVALID ANS TYPE"; + std::cerr << std::endl; + break; + } + break; +#endif + default: + std::cerr << "WireDialog::loadRequest() ERROR: INVALID TYPE"; + std::cerr << std::endl; + break; + } + } +} + + +/**************************** Request / Response Filling of Data ************************/ diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.h b/retroshare-gui/src/gui/TheWire/WireDialog.h index ae948b958..e50823ffd 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.h +++ b/retroshare-gui/src/gui/TheWire/WireDialog.h @@ -1,7 +1,7 @@ /******************************************************************************* * gui/TheWire/WireDialog.h * * * - * Copyright (c) 2012 Robert Fernie * + * Copyright (c) 2012-2020 Robert Fernie * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Affero General Public License as * @@ -24,67 +24,75 @@ #include "retroshare-gui/mainpage.h" #include "ui_WireDialog.h" -#include +#include #include #include "gui/TheWire/PulseItem.h" #include "gui/TheWire/PulseAddDialog.h" +#include "util/TokenQueue.h" + #define IMAGE_WIRE ":/images/kgames.png" -class WireDialog : public MainPage, public PulseHolder +class WireDialog : public MainPage, public TokenResponse, public PulseHolder { Q_OBJECT public: WireDialog(QWidget *parent = 0); - virtual QIcon iconPixmap() const { return QIcon(IMAGE_WIRE) ; } - virtual QString pageName() const { return tr("The Wire") ; } - virtual QString helpText() const { return ""; } + virtual QIcon iconPixmap() const { return QIcon(IMAGE_WIRE) ; } + virtual QString pageName() const { return tr("The Wire") ; } + virtual QString helpText() const { return ""; } -virtual void deletePulseItem(PulseItem *, uint32_t type); -virtual void notifySelection(PulseItem *item, int ptype); + // PulseHolder interface. + virtual void deletePulseItem(PulseItem *, uint32_t type); + virtual void notifySelection(PulseItem *item, int ptype); + + virtual void follow(RsGxsGroupId &groupId); + virtual void rate(RsGxsId &authorId); + virtual void reply(RsWirePulse &pulse, std::string &groupName); void notifyPulseSelection(PulseItem *item); private slots: + void createGroup(); + void createPulse(); void checkUpdate(); - void OpenOrShowPulseAddDialog(); + void refreshGroups(); private: + void addItem(QWidget *item); + void addGroup(QWidget *item); + void addPulse(RsWirePulse &pulse, RsWireGroup &group); + void addGroup(RsWireGroup &group); - /* TODO: These functions must be filled in for proper filtering to work - * and tied to the GUI input - */ + void deletePulses(); + void deleteGroups(); + void updateGroups(std::vector &groups); - bool matchesAlbumFilter(const RsPhotoAlbum &album); - double AlbumScore(const RsPhotoAlbum &album); - bool matchesPhotoFilter(const RsPhotoPhoto &photo); - double PhotoScore(const RsPhotoPhoto &photo); + // Loading Data. + void requestGroupData(); + bool loadGroupData(const uint32_t &token); - /* Grunt work of setting up the GUI */ + void requestPulseData(const std::list& grpIds); + bool loadPulseData(const uint32_t &token); - bool FilterNSortAlbums(const std::list &albumIds, std::list &filteredAlbumIds, int count); - bool FilterNSortPhotos(const std::list &photoIds, std::list &filteredPhotoIds, int count); - void insertAlbums(); - void insertPhotosForAlbum(const std::list &albumIds); - void insertPhotosForSelectedAlbum(); - - void addAlbum(const std::string &id); - void addPhoto(const std::string &id); - - void clearAlbums(); - void clearPhotos(); + virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); PulseAddDialog *mAddDialog; PulseItem *mPulseSelected; + TokenQueue *mWireQueue; + + std::map mAllGroups; + std::vector mOwnGroups; + /* UI - from Designer */ Ui::WireDialog ui; diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.ui b/retroshare-gui/src/gui/TheWire/WireDialog.ui index 3f6074b37..ee69ee56b 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.ui +++ b/retroshare-gui/src/gui/TheWire/WireDialog.ui @@ -10,16 +10,168 @@ 557 + + + 0 + 0 + + - + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Create Account + + + + + + + Post Pulse + + + + + + + ... + + + + + + + ... + + + + + + + ... + + + + + + + Qt::Horizontal + + + + 296 + 20 + + + + + + + + Refresh + + + + + + + + + + Settings + + + + + + + + + + true + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + 0 + 0 + 567 + 412 + + + + QWidget#scrollAreaWidgetContents{border: none;} + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + - - + + + + + - TimeRange + Search/Filter + + + + + + + Network Wide @@ -66,40 +218,23 @@ - - - - - + + - Search/Filter + TimeRange - - - - Network Wide - - - - - - - Manage Accounts - - - - + - 160 + 200 16777215 @@ -113,7 +248,16 @@ 0 - + + 0 + + + 0 + + + 0 + + 0 @@ -121,126 +265,16 @@ true - + 0 0 - 156 - 469 + 129 + 416 - - - - Showing: - - - - 0 - - - - - Yourself - - - - - - - Friends - - - - - - - Following - - - - - - - All - - - - - - - Qt::Horizontal - - - - - - - Custom - - - - - - - - - - Account 1 - - - - - - - Account 2 - - - - - - - Account 3 - - - - - - - CheckBox - - - - - - - CheckBox - - - - - - - CheckBox - - - - - - - CheckBox - - - - - - - CheckBox - - - @@ -261,51 +295,36 @@ - - - - true - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - 0 - 0 - 540 - 465 - + + + + + Yourself - - QWidget#scrollAreaWidgetContents{border: none;} + + + + Subscribed - - - 0 - - - 0 - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - + + + + Auto + + + + + Recommended + + + + + Others + + - + Post Pulse to Wire @@ -315,7 +334,7 @@ - + diff --git a/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp b/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp new file mode 100644 index 000000000..119d29a9f --- /dev/null +++ b/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp @@ -0,0 +1,180 @@ +/******************************************************************************* + * gui/TheWire/WireGroupDialog.cpp * + * * + * Copyright (C) 2020 by Robert Fernie * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ +#include + +#include "WireGroupDialog.h" +#include "gui/gxs/GxsIdDetails.h" + +#include + +const uint32_t WireCreateEnabledFlags = ( + GXS_GROUP_FLAGS_NAME | + GXS_GROUP_FLAGS_ICON | + GXS_GROUP_FLAGS_DESCRIPTION | + GXS_GROUP_FLAGS_DISTRIBUTION | + // GXS_GROUP_FLAGS_PUBLISHSIGN | + // GXS_GROUP_FLAGS_SHAREKEYS | // disabled because the UI doesn't handle it yet. + // GXS_GROUP_FLAGS_PERSONALSIGN | + // GXS_GROUP_FLAGS_COMMENTS | + GXS_GROUP_FLAGS_EXTRA | + 0); + +uint32_t WireCreateDefaultsFlags = ( GXS_GROUP_DEFAULTS_DISTRIB_PUBLIC | + // GXS_GROUP_DEFAULTS_DISTRIB_GROUP | + // GXS_GROUP_DEFAULTS_DISTRIB_LOCAL | + + GXS_GROUP_DEFAULTS_PUBLISH_OPEN | + // GXS_GROUP_DEFAULTS_PUBLISH_THREADS | + // GXS_GROUP_DEFAULTS_PUBLISH_REQUIRED | + // GXS_GROUP_DEFAULTS_PUBLISH_ENCRYPTED | + + // GXS_GROUP_DEFAULTS_PERSONAL_GPG | + GXS_GROUP_DEFAULTS_PERSONAL_REQUIRED | + // GXS_GROUP_DEFAULTS_PERSONAL_IFNOPUB | + + // GXS_GROUP_DEFAULTS_COMMENTS_YES | + GXS_GROUP_DEFAULTS_COMMENTS_NO | + 0); + +uint32_t WireEditEnabledFlags = WireCreateEnabledFlags; +uint32_t WireEditDefaultsFlags = WireCreateDefaultsFlags; + +WireGroupDialog::WireGroupDialog(TokenQueue *tokenQueue, QWidget *parent) + : GxsGroupDialog(tokenQueue, WireCreateEnabledFlags, WireCreateDefaultsFlags, parent) +{ +} + +WireGroupDialog::WireGroupDialog(TokenQueue *tokenExternalQueue, RsTokenService *tokenService, Mode mode, RsGxsGroupId groupId, QWidget *parent) + : GxsGroupDialog(tokenExternalQueue, tokenService, mode, groupId, WireEditEnabledFlags, WireEditDefaultsFlags, parent) +{ +} + +void WireGroupDialog::initUi() +{ + switch (mode()) + { + case MODE_CREATE: + setUiText(UITYPE_SERVICE_HEADER, tr("Create New Wire")); + setUiText(UITYPE_BUTTONBOX_OK, tr("Create")); + break; + case MODE_SHOW: + setUiText(UITYPE_SERVICE_HEADER, tr("Wire")); + break; + case MODE_EDIT: + setUiText(UITYPE_SERVICE_HEADER, tr("Edit Wire")); + setUiText(UITYPE_BUTTONBOX_OK, tr("Update Wire")); + break; + } + + setUiText(UITYPE_ADD_ADMINS_CHECKBOX, tr("Add Wire Admins")); + setUiText(UITYPE_CONTACTS_DOCK, tr("Select Wire Admins")); +} + +QPixmap WireGroupDialog::serviceImage() +{ + return QPixmap(":/images/wire_create_64.png"); +} + +void WireGroupDialog::prepareWireGroup(RsWireGroup &group, const RsGroupMetaData &meta) +{ + group.mMeta = meta; + group.mDescription = getDescription().toUtf8().constData(); + +#if 0 + QPixmap pixmap = getLogo(); + + if (!pixmap.isNull()) { + QByteArray ba; + QBuffer buffer(&ba); + + buffer.open(QIODevice::WriteOnly); + pixmap.save(&buffer, "PNG"); // writes image into ba in PNG format + + group.mThumbnail.copy((uint8_t *) ba.data(), ba.size()); + } else { + group.mThumbnail.clear(); + } +#endif + +} + +bool WireGroupDialog::service_CreateGroup(uint32_t &token, const RsGroupMetaData &meta) +{ + // Specific Function. + RsWireGroup grp; + prepareWireGroup(grp, meta); + + rsWire->createGroup(token, grp); + return true; +} + +bool WireGroupDialog::service_EditGroup(uint32_t &token, RsGroupMetaData &editedMeta) +{ + RsWireGroup grp; + prepareWireGroup(grp, editedMeta); + + std::cerr << "WireGroupDialog::service_EditGroup() submitting changes"; + std::cerr << std::endl; + + // TODO: no interface here, yet. + // rsWire->updateGroup(token, grp); + return true; +} + +bool WireGroupDialog::service_loadGroup(uint32_t token, Mode /*mode*/, RsGroupMetaData& groupMetaData, QString &description) +{ + std::cerr << "WireGroupDialog::service_loadGroup(" << token << ")"; + std::cerr << std::endl; + + std::vector groups; + if (!rsWire->getGroupData(token, groups)) + { + std::cerr << "WireGroupDialog::service_loadGroup() Error getting GroupData"; + std::cerr << std::endl; + return false; + } + + if (groups.size() != 1) + { + std::cerr << "WireGroupDialog::service_loadGroup() Error Group.size() != 1"; + std::cerr << std::endl; + return false; + } + + std::cerr << "WireGroupDialog::service_loadGroup() Unfinished Loading"; + std::cerr << std::endl; + + const RsWireGroup &group = groups[0]; + groupMetaData = group.mMeta; + description = QString::fromUtf8(group.mDescription.c_str()); + +#if 0 + if (group.mThumbnail.mData) { + QPixmap pixmap; + if (GxsIdDetails::loadPixmapFromData(group.mThumbnail.mData, group.mThumbnail.mSize, pixmap,GxsIdDetails::ORIGINAL)) { + setLogo(pixmap); + } + } else { + setLogo(QPixmap(":/images/album_create_64.png")); + } +#endif + + return true; +} diff --git a/retroshare-gui/src/gui/TheWire/WireGroupDialog.h b/retroshare-gui/src/gui/TheWire/WireGroupDialog.h new file mode 100644 index 000000000..9a4b614c9 --- /dev/null +++ b/retroshare-gui/src/gui/TheWire/WireGroupDialog.h @@ -0,0 +1,46 @@ +/******************************************************************************* + * gui/TheWire/WireGroupDialog.h * + * * + * Copyright (C) 2020 by Robert Fernie * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +#ifndef _WIRE_GROUP_DIALOG_H +#define _WIRE_GROUP_DIALOG_H + +#include "gui/gxs/GxsGroupDialog.h" +#include + +class WireGroupDialog : public GxsGroupDialog +{ + Q_OBJECT + +public: + WireGroupDialog(TokenQueue *tokenQueue, QWidget *parent); + WireGroupDialog(TokenQueue *tokenExternalQueue, RsTokenService *tokenService, Mode mode, RsGxsGroupId groupId, QWidget *parent); + +protected: + virtual void initUi(); + virtual QPixmap serviceImage(); + virtual bool service_CreateGroup(uint32_t &token, const RsGroupMetaData &meta); + virtual bool service_loadGroup(uint32_t token, Mode mode, RsGroupMetaData& groupMetaData, QString &description); + virtual bool service_EditGroup(uint32_t &token, RsGroupMetaData &editedMeta); + +private: + void prepareWireGroup(RsWireGroup &group, const RsGroupMetaData &meta); +}; + +#endif diff --git a/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp b/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp new file mode 100644 index 000000000..5c5606943 --- /dev/null +++ b/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp @@ -0,0 +1,92 @@ +/******************************************************************************* + * gui/TheWire/WireGroupItem.cpp * + * * + * Copyright (c) 2020 Robert Fernie * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +#include +#include +#include +#include + +#include "WireGroupItem.h" + +#include +#include + +/** Constructor */ + +WireGroupItem::WireGroupItem(RsWireGroup grp) +:QWidget(NULL), mGroup(grp), mType(0) +{ + setupUi(this); + setAttribute ( Qt::WA_DeleteOnClose, true ); + setup(); + +} + +void WireGroupItem::setup() +{ + label_groupName->setText(QString::fromStdString(mGroup.mMeta.mGroupName)); + // label_authorId->setText(mGroup.mMeta.mAuthorId); + frame_details->setVisible(false); + + connect(toolButton_show, SIGNAL(clicked()), this, SLOT(show())); +} + +void WireGroupItem::show() +{ + frame_details->setVisible(!frame_details->isVisible()); +} + + +void WireGroupItem::removeItem() +{ +} + +void WireGroupItem::setSelected(bool on) +{ +} + +bool WireGroupItem::isSelected() +{ + return mSelected; +} + +void WireGroupItem::mousePressEvent(QMouseEvent *event) +{ + /* We can be very cunning here? + * grab out position. + * flag ourselves as selected. + * then pass the mousePressEvent up for handling by the parent + */ + + QPoint pos = event->pos(); + + std::cerr << "WireGroupItem::mousePressEvent(" << pos.x() << ", " << pos.y() << ")"; + std::cerr << std::endl; + + setSelected(true); + + QWidget::mousePressEvent(event); +} + +const QPixmap *WireGroupItem::getPixmap() +{ + return NULL; +} + diff --git a/retroshare-gui/src/gui/TheWire/WireGroupItem.h b/retroshare-gui/src/gui/TheWire/WireGroupItem.h new file mode 100644 index 000000000..9f6eac14f --- /dev/null +++ b/retroshare-gui/src/gui/TheWire/WireGroupItem.h @@ -0,0 +1,58 @@ +/******************************************************************************* + * gui/TheWire/WireGroupItem.h * + * * + * Copyright (c) 2020 Robert Fernie * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +#ifndef MRK_WIRE_GROUP_ITEM_H +#define MRK_WIRE_GROUP_ITEM_H + +#include "ui_WireGroupItem.h" + +#include + +class WireGroupItem; + +class WireGroupItem : public QWidget, private Ui::WireGroupItem +{ + Q_OBJECT + +public: + WireGroupItem(RsWireGroup grp); + + void removeItem(); + + void setSelected(bool on); + bool isSelected(); + + const QPixmap *getPixmap(); + +private slots: + void show(); + +protected: + void mousePressEvent(QMouseEvent *event); + +private: + void setup(); + + RsWireGroup mGroup; + uint32_t mType; + bool mSelected; +}; + +#endif diff --git a/retroshare-gui/src/gui/TheWire/WireGroupItem.ui b/retroshare-gui/src/gui/TheWire/WireGroupItem.ui new file mode 100644 index 000000000..f5939e03b --- /dev/null +++ b/retroshare-gui/src/gui/TheWire/WireGroupItem.ui @@ -0,0 +1,110 @@ + + + WireGroupItem + + + + 0 + 0 + 276 + 114 + + + + Form + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + WireGroupName + + + + + + + Qt::Horizontal + + + + 118 + 20 + + + + + + + + Type + + + + + + + \/ + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + GxsIdLabel + + + + + + + Qt::Horizontal + + + + 61 + 20 + + + + + + + + Sub/Un + + + + + + + + + + + + + + From a089bc6e0667e952bf4801e94b2ff1011b331132 Mon Sep 17 00:00:00 2001 From: drbob Date: Sun, 1 Mar 2020 09:37:42 +1100 Subject: [PATCH 2/2] add missing files to retroshare-gui.pro --- retroshare-gui/src/retroshare-gui.pro | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/retroshare-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro index f0a901e39..01bb92012 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -1225,15 +1225,23 @@ gxsthewire { DEFINES += RS_USE_WIRE HEADERS += gui/TheWire/PulseItem.h \ + gui/TheWire/PulseDetails.h \ gui/TheWire/WireDialog.h \ + gui/TheWire/WireGroupItem.h \ + gui/TheWire/WireGroupDialog.h \ gui/TheWire/PulseAddDialog.h \ FORMS += gui/TheWire/PulseItem.ui \ + gui/TheWire/PulseDetails.ui \ + gui/TheWire/WireGroupItem.ui \ gui/TheWire/WireDialog.ui \ gui/TheWire/PulseAddDialog.ui \ SOURCES += gui/TheWire/PulseItem.cpp \ + gui/TheWire/PulseDetails.cpp \ gui/TheWire/WireDialog.cpp \ + gui/TheWire/WireGroupItem.cpp \ + gui/TheWire/WireGroupDialog.cpp \ gui/TheWire/PulseAddDialog.cpp \ }