Message Synchronisation now supported by photoshare (photo and comments sync)

Photoshare UI now functional 
- subscribing to an album enables message sync
- TokenQueue now operate with FIFO stack to prevent overlap in request completion
- photos are now load on demand as with comments
- fixed some noddy bugs (subscribe flag initialises incorrectly)


git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-gxs-b1@5624 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
chrisparker126 2012-09-30 14:21:17 +00:00
parent bdd6c6041b
commit b06214b779
12 changed files with 240 additions and 102 deletions

View File

@ -558,11 +558,6 @@ void RsGenExchange::publishMsgs()
msg->metaData = new RsGxsMsgMetaData();
msg->msg.setBinData(mData, size);
*(msg->metaData) = msgItem->meta;
size = msg->metaData->serial_size();
char metaDataBuff[size];
msg->metaData->serialise(metaDataBuff, &size);
msg->meta.setBinData(metaDataBuff, size);
ok = createMessage(msg);
RsGxsMessageId msgId;
@ -582,6 +577,14 @@ void RsGenExchange::publishMsgs()
{
msg->metaData->mOrigMsgId = msg->metaData->mMsgId;
}
// now serialise meta data
size = msg->metaData->serial_size();
char metaDataBuff[size];
msg->metaData->serialise(metaDataBuff, &size);
msg->meta.setBinData(metaDataBuff, size);
msgId = msg->msgId;
grpId = msg->grpId;
ok = mDataAccess->addMsgData(msg);
@ -716,11 +719,50 @@ void RsGenExchange::createDummyGroup(RsGxsGrpItem *grpItem)
void RsGenExchange::processRecvdData()
{
processRecvdGroups();
processRecvdMessages();
}
void RsGenExchange::processRecvdMessages()
{
RsStackMutex stack(mGenMtx);
std::vector<RsNxsMsg*>::iterator vit = mReceivedMsgs.begin();
GxsMsgReq msgIds;
std::map<RsNxsMsg*, RsGxsMsgMetaData*> msgs;
for(; vit != mReceivedMsgs.end(); vit++)
{
RsNxsMsg* msg = *vit;
RsGxsMsgMetaData* meta = new RsGxsMsgMetaData();
bool ok = meta->deserialise(msg->meta.bin_data, &(msg->meta.bin_len));
if(ok)
{
msgs.insert(std::make_pair(msg, meta));
msgIds[msg->grpId].push_back(msg->msgId);
}
else
{
#ifdef GXS_GENX_DEBUG
std::cerr << "failed to deserialise incoming meta, grpId: "
<< msg->grpId << ", msgId: " << msg->msgId << std::endl;
#endif
delete msg;
delete meta;
}
}
if(!msgIds.empty())
{
mDataStore->storeMessage(msgs);
RsGxsMsgChange* c = new RsGxsMsgChange();
c->msgChangeMap = msgIds;
mNotifications.push_back(c);
}
mReceivedMsgs.clear();
}
@ -737,11 +779,22 @@ void RsGenExchange::processRecvdGroups()
{
RsNxsGrp* grp = *vit;
RsGxsGrpMetaData* meta = new RsGxsGrpMetaData();
meta->deserialise(grp->meta.bin_data, grp->meta.bin_len);
grps.insert(std::make_pair(grp, meta));
grpIds.push_back(grp->grpId);
bool ok = meta->deserialise(grp->meta.bin_data, grp->meta.bin_len);
if(ok)
{
grps.insert(std::make_pair(grp, meta));
grpIds.push_back(grp->grpId);
}
else
{
#ifdef GXS_GENX_DEBUG
std::cerr << "failed to deserialise incoming meta, grpId: "
<< grp->grpId << std::endl;
#endif
delete grp;
delete meta;
}
}
if(!grpIds.empty())

View File

@ -30,7 +30,7 @@
RsGxsGrpMetaData::RsGxsGrpMetaData()
{
clear();
}
uint32_t RsGxsGrpMetaData::serial_size()

View File

@ -98,7 +98,8 @@ void RsGxsNetService::syncWithPeers()
{
RsGxsGrpMetaData* meta = mit->second;
if(meta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED)
if(meta->mSubscribeFlags & (GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED |
GXS_SERV::GROUP_SUBSCRIBE_ADMIN) )
grpIds.push_back(mit->first);
delete meta;
@ -106,21 +107,21 @@ void RsGxsNetService::syncWithPeers()
sit = peers.begin();
// TODO msgs
// synchronise group msg for groups which we're subscribed to
for(; sit != peers.end(); sit++)
{
RsStackMutex stack(mNxsMutex);
RsStackMutex stack(mNxsMutex);
std::vector<RsGxsGroupId>::iterator vit = grpIds.begin();
std::vector<RsGxsGroupId>::iterator vit = grpIds.begin();
for(; vit != grpIds.end(); vit++)
{
RsNxsSyncMsg* msg = new RsNxsSyncMsg(mServType);
msg->clear();
msg->PeerId(*sit);
msg->grpId = *vit;
sendItem(msg);
}
for(; vit != grpIds.end(); vit++)
{
RsNxsSyncMsg* msg = new RsNxsSyncMsg(mServType);
msg->clear();
msg->PeerId(*sit);
msg->grpId = *vit;
sendItem(msg);
}
}
}

View File

@ -126,7 +126,15 @@ void p3PhotoServiceV2::groupsChanged(std::list<RsGxsGroupId>& grpIds)
void p3PhotoServiceV2::msgsChanged(
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >& msgs)
{
RsStackMutex stack(mPhotoMutex);
while(!mMsgChange.empty())
{
RsGxsMsgChange* mc = mMsgChange.back();
msgs = mc->msgChangeMap;
mMsgChange.pop_back();
delete mc;
}
}

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>479</width>
<height>89</height>
<width>411</width>
<height>84</height>
</rect>
</property>
<property name="windowTitle">
@ -16,6 +16,18 @@
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QFrame" name="expandFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>400</width>
<height>71</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QFrame#expandFrame{border: 2px solid #D3D3D3;
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,

View File

@ -13,9 +13,8 @@ PhotoDialog::PhotoDialog(RsPhotoV2 *rs_photo, const RsPhotoPhoto &photo, QWidget
{
ui->setupUi(this);
setAttribute ( Qt::WA_DeleteOnClose, true );
setUp();
connect(ui->toolButton_AddComment, SIGNAL(clicked()), this, SLOT(addComment()));
setUp();
}
@ -33,6 +32,8 @@ void PhotoDialog::setUp()
ui->lineEdit_Title->setText(QString::fromStdString(mPhotoDetails.mMeta.mMsgName));
ui->scrollAreaWidgetContents->setLayout(new QVBoxLayout());
requestComments();
}
@ -55,13 +56,14 @@ void PhotoDialog::clearComments()
PhotoCommentItem* item = sit.next();
l->removeWidget(item);
item->setParent(NULL);
delete item;
}
mComments.clear();
}
void PhotoDialog::resetComments()
{
clearComments();
QSetIterator<PhotoCommentItem*> sit(mComments);
QLayout* l = ui->scrollAreaWidgetContents->layout();
while(sit.hasNext())
@ -71,6 +73,21 @@ void PhotoDialog::resetComments()
}
}
void PhotoDialog::requestComments()
{
RsTokReqOptionsV2 opts;
opts.mMsgFlagMask = RsPhotoV2::FLAG_MSG_TYPE_MASK;
opts.mMsgFlagFilter = RsPhotoV2::FLAG_MSG_TYPE_PHOTO_COMMENT;
opts.mReqType = GXS_REQUEST_TYPE_MSG_IDS;
opts.mOptions = RS_TOKREQOPT_MSG_PARENT | RS_TOKREQOPT_MSG_LATEST;
RsGxsGrpMsgIdPair msgId;
uint32_t token;
msgId.first = mPhotoDetails.mMeta.mGroupId;
msgId.second = mPhotoDetails.mMeta.mMsgId;
mPhotoQueue->requestMsgRelatedInfo(token, opts, msgId, 0);
}
void PhotoDialog::createComment()
{
if(mCommentDialog)
@ -82,6 +99,7 @@ void PhotoDialog::createComment()
uint32_t token;
comment.mMeta.mGroupId = mPhotoDetails.mMeta.mGroupId;
comment.mMeta.mParentId = mPhotoDetails.mMeta.mOrigMsgId;
mRsPhoto->submitComment(token, comment);
mPhotoQueue->queueRequest(token, TOKENREQ_MSGINFO, RS_TOKREQ_ANSTYPE_ACK, 0);
@ -111,6 +129,9 @@ void PhotoDialog::loadRequest(const TokenQueueV2 *queue, const TokenRequestV2 &r
case RS_TOKREQ_ANSTYPE_DATA:
loadComment(req.mToken);
break;
case RS_TOKREQ_ANSTYPE_LIST:
loadList(req.mToken);
break;
case RS_TOKREQ_ANSTYPE_ACK:
acknowledgeComment(req.mToken);
break;
@ -136,6 +157,8 @@ void PhotoDialog::loadRequest(const TokenQueueV2 *queue, const TokenRequestV2 &r
void PhotoDialog::loadComment(uint32_t token)
{
clearComments();
PhotoCommentResult results;
mRsPhoto->getPhotoComment(token, results);
@ -155,6 +178,18 @@ void PhotoDialog::loadComment(uint32_t token)
resetComments();
}
void PhotoDialog::loadList(uint32_t token)
{
GxsMsgReq msgIds;
mRsPhoto->getMsgList(token, msgIds);
RsTokReqOptionsV2 opts;
// just use data as no need to worry about getting comments
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
uint32_t reqToken;
mPhotoQueue->requestMsgInfo(reqToken, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, 0);
}
void PhotoDialog::addComment(const RsPhotoComment &comment)
{
PhotoCommentItem* item = new PhotoCommentItem(comment);
@ -170,16 +205,7 @@ void PhotoDialog::acknowledgeComment(uint32_t token)
}else
{
uint32_t reqToken;
RsTokReqOptionsV2 opts;
opts.mMsgFlagMask = RsPhotoV2::FLAG_MSG_TYPE_MASK;
opts.mMsgFlagFilter = RsPhotoV2::FLAG_MSG_TYPE_PHOTO_COMMENT;
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
GxsMsgReq req;
std::vector<RsGxsMessageId> msgIdsV;
msgIdsV.push_back(msgId.second);
req.insert(std::make_pair(msgId.first, msgIdsV));
mPhotoQueue->requestMsgInfo(reqToken, RS_TOKREQ_ANSTYPE_DATA, opts, req, 0);
requestComments();
}
}

View File

@ -36,6 +36,11 @@ private:
*/
void resetComments();
/*!
* Request comments
*/
void requestComments();
/*!
* Simply removes comments but doesn't place them back in dialog
*/
@ -43,6 +48,7 @@ private:
void acknowledgeComment(uint32_t token);
void loadComment(uint32_t token);
void loadList(uint32_t token);
void addComment(const RsPhotoComment& comment);
private:
Ui::PhotoDialog *ui;

View File

@ -32,12 +32,12 @@ PhotoItem::PhotoItem(PhotoShareItemHolder *holder, const QString& path, QWidget
{
ui->setupUi(this);
int width = 120;
int height = 120;
int width = 250;
int height = 250;
QPixmap qtn = QPixmap(path).scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation);
ui->label_Thumbnail->setPixmap(qtn);
mThumbNail = qtn;
ui->label_Thumbnail->setPixmap(mThumbNail.scaled(120, 120, Qt::KeepAspectRatio, Qt::SmoothTransformation));
setSelected(false);
getPhotoThumbnail(mPhotoDetails.mThumbnail);

View File

@ -98,7 +98,6 @@ PhotoShare::PhotoShare(QWidget *parent)
/* setup TokenQueue */
mPhotoQueue = new TokenQueueV2(rsPhotoV2->getTokenService(), this);
requestAlbumData();
updateAlbums();
}
void PhotoShare::notifySelection(PhotoShareItem *selection)
@ -113,8 +112,6 @@ void PhotoShare::notifySelection(PhotoShareItem *selection)
if(mPhotoSelected)
mPhotoSelected->setSelected(false);
clearPhotos();
if(mAlbumSelected == aItem)
{
mAlbumSelected->setSelected(true);
@ -133,9 +130,11 @@ void PhotoShare::notifySelection(PhotoShareItem *selection)
mAlbumSelected->setSelected(true);
// get photo data
std::list<RsGxsGroupId> grpIds;
grpIds.push_back(mAlbumSelected->getAlbum().mMeta.mGroupId);
requestPhotoData(grpIds);
}
updatePhotos();
}
else if((pItem = dynamic_cast<PhotoItem*>(selection)) != NULL)
{
@ -283,6 +282,8 @@ void PhotoShare::SetPhotoDialogClosed()
void PhotoShare::clearAlbums()
{
clearPhotos();
std::cerr << "PhotoShare::clearAlbums()" << std::endl;
QLayout *alayout = ui.scrollAreaWidgetContents->layout();
@ -295,8 +296,6 @@ void PhotoShare::clearAlbums()
item->setParent(NULL);
}
clearPhotos();
// set no albums to be selected
if(mAlbumSelected)
{
@ -328,23 +327,23 @@ void PhotoShare::deleteAlbums()
void PhotoShare::clearPhotos()
{
std::cerr << "PhotoShare::clearPhotos()" << std::endl;
mPhotoSelected = NULL;
QLayout *layout = ui.scrollAreaWidgetContents_2->layout();
if(mAlbumSelected)
{
const RsGxsGroupId& id = mAlbumSelected->getAlbum().mMeta.mGroupId;
QSetIterator<PhotoItem*> sit(mPhotoItems[id]);
QSetIterator<PhotoItem*> sit(mPhotoItems);
while(sit.hasNext())
{
PhotoItem* item = sit.next();
layout->removeWidget(item);
item->setParent(NULL);
delete item; // remove item
}
mPhotoItems.clear();
}
mPhotoSelected = NULL;
}
void PhotoShare::updateAlbums()
@ -407,10 +406,38 @@ void PhotoShare::updateAlbums()
}
}
void PhotoShare::deleteAlbum(const RsGxsGroupId &grpId)
{
QSetIterator<AlbumItem*> sit(mAlbumItems);
while(sit.hasNext())
{
AlbumItem* item = sit.next();
if(item->getAlbum().mMeta.mGroupId == grpId){
if(mAlbumSelected == item)
{
item->setSelected(false);
mAlbumSelected = NULL;
}
QLayout *alayout = ui.scrollAreaWidgetContents->layout();
alayout->removeWidget(item);
mAlbumItems.remove(item);
item->setParent(NULL);
delete item;
return;
}
}
}
void PhotoShare::addAlbum(const RsPhotoAlbum &album)
{
std::cerr << " PhotoShare::addAlbum() AlbumId: " << album.mMeta.mGroupId << std::endl;
deleteAlbum(album.mMeta.mGroupId); // remove from ui
AlbumItem *item = new AlbumItem(album, this, this);
mAlbumItems.insert(item);
}
@ -423,9 +450,7 @@ void PhotoShare::addPhoto(const RsPhotoPhoto &photo)
std::cerr << std::endl;
PhotoItem* item = new PhotoItem(this, photo, this);
const RsGxsGroupId id = photo.mMeta.mGroupId;
mPhotoItems[id].insert(item);
mPhotoItems.insert(item);
}
void PhotoShare::subscribeToAlbum()
@ -450,13 +475,10 @@ void PhotoShare::subscribeToAlbum()
void PhotoShare::updatePhotos()
{
clearPhotos();
if(mAlbumSelected)
{
const RsGxsGroupId& grpId = mAlbumSelected->getAlbum().mMeta.mGroupId;
QSetIterator<PhotoItem*> sit(mPhotoItems[grpId]);
QSetIterator<PhotoItem*> sit(mPhotoItems);
while(sit.hasNext())
{
@ -497,8 +519,6 @@ void PhotoShare::loadAlbumList(const uint32_t &token)
requestAlbumData(albumIds);
clearPhotos();
std::list<std::string>::iterator it;
for(it = albumIds.begin(); it != albumIds.end(); it++)
{
@ -525,9 +545,6 @@ void PhotoShare::requestAlbumData()
bool PhotoShare::loadAlbumData(const uint32_t &token)
{
deleteAlbums();
std::cerr << "PhotoShare::loadAlbumData()";
std::cerr << std::endl;
@ -544,6 +561,7 @@ bool PhotoShare::loadAlbumData(const uint32_t &token)
addAlbum(album);
}
updateAlbums();
return true;
}
@ -575,7 +593,7 @@ void PhotoShare::acknowledgeGroup(const uint32_t &token)
RsTokReqOptionsV2 opts;
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
uint32_t reqToken;
mPhotoQueue->requestGroupInfo(reqToken, RS_TOKREQ_ANSTYPE_DATA, opts, 0);
mPhotoQueue->requestGroupInfo(reqToken, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds, 0);
}
}
@ -584,18 +602,21 @@ void PhotoShare::acknowledgeMessage(const uint32_t &token)
std::pair<RsGxsGroupId, RsGxsMessageId> p;
rsPhotoV2->acknowledgeMsg(token, p);
if(!p.first.empty())
{
GxsMsgReq req;
std::vector<RsGxsMessageId> v;
v.push_back(p.second);
req[p.first] = v;
RsTokReqOptionsV2 opts;
opts.mOptions = RS_TOKREQOPT_MSG_LATEST;
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
uint32_t reqToken;
mPhotoQueue->requestMsgInfo(reqToken, RS_TOKREQ_ANSTYPE_DATA, opts, req, 0);
}
// just acknowledge don't load it
// loading is only instigated by clicking an album (i.e. requesting photo data)
// but load it if the album is selected
// if(!p.first.empty())
// {
// if(mAlbumSelected)
// {
// if(mAlbumSelected->getAlbum().mMeta.mGroupId == p.first)
// {
// std::list<RsGxsGroupId> grpIds;
// grpIds.push_back(p.first);
// requestPhotoData(grpIds);
// }
// }
// }
}
void PhotoShare::loadPhotoList(const uint32_t &token)
@ -618,12 +639,22 @@ void PhotoShare::requestPhotoData(GxsMsgReq &photoIds)
mPhotoQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, photoIds, 0);
}
void PhotoShare::requestPhotoData(const std::list<RsGxsGroupId>& grpIds)
{
RsTokReqOptionsV2 opts;
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
uint32_t token;
mPhotoQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds, 0);
}
void PhotoShare::loadPhotoData(const uint32_t &token)
{
std::cerr << "PhotoShare::loadPhotoData()";
std::cerr << std::endl;
clearPhotos();
PhotoResult res;
rsPhotoV2->getPhoto(token, res);
PhotoResult::iterator mit = res.begin();

View File

@ -43,6 +43,7 @@ private slots:
void SetPhotoDialogClosed();
void updateAlbums();
void subscribeToAlbum();
void deleteAlbum(const RsGxsGroupId&);
private:
/* Request Response Functions for loading data */
@ -56,6 +57,7 @@ private:
void requestPhotoList(GxsMsgReq &albumIds);
void requestPhotoList(const std::string &albumId);
void requestPhotoData(GxsMsgReq &photoIds);
void requestPhotoData(const std::list<RsGxsGroupId> &grpIds);
void loadAlbumList(const uint32_t &token);
bool loadAlbumData(const uint32_t &token);
@ -75,6 +77,9 @@ private:
void clearAlbums();
void clearPhotos();
void deleteAlbums();
/*!
* Fills up photo ui with photos held in mPhotoItems (current groups photos)
*/
void updatePhotos();
private:
@ -92,7 +97,7 @@ private:
Ui::PhotoShare ui;
QSet<AlbumItem*> mAlbumItems;
QMap<RsGxsGroupId, QSet<PhotoItem*> > mPhotoItems;
QSet<PhotoItem*> mPhotoItems; // the current album selected
};

View File

@ -104,7 +104,7 @@ void TokenQueueV2::queueRequest(uint32_t token, uint32_t basictype, uint32_t ans
gettimeofday(&req.mRequestTs, NULL);
req.mPollTs = req.mRequestTs;
mRequests.push_back(req);
mRequests.push_back(req);
if (mRequests.size() == 1)
{
@ -123,26 +123,23 @@ void TokenQueueV2::doPoll(float dt)
void TokenQueueV2::pollRequests()
{
std::list<TokenRequestV2>::iterator it;
double pollPeriod = 1.0; // max poll period.
for(it = mRequests.begin(); it != mRequests.end();)
{
if (checkForRequest(it->mToken))
{
/* clean it up and handle */
loadRequest(*it);
it = mRequests.erase(it);
}
else
{
/* calculate desired poll period */
/* if less then current poll period, adjust */
it++;
}
}
TokenRequestV2 req;
if(mRequests.size() > 0){
req = mRequests.front();
}else
{
return;
}
if (checkForRequest(req.mToken))
{
/* clean it up and handle */
loadRequest(req);
mRequests.pop_front();
}
if (mRequests.size() > 0)
{
@ -178,7 +175,7 @@ bool TokenQueueV2::cancelRequest(const uint32_t token)
/* cancel at lower level first */
mService->cancelRequest(token);
std::list<TokenRequestV2>::iterator it;
std::list<TokenRequestV2>::iterator it;
for(it = mRequests.begin(); it != mRequests.end(); it++)
{

View File

@ -64,9 +64,8 @@ class TokenResponseV2
/*!
*
*
*
* An important thing to note is that all requests are stacked (so FIFO)
* This is to prevent overlapped loads on GXS UIs
*/
class TokenQueueV2: public QWidget
{
@ -110,7 +109,7 @@ private slots:
private:
/* Info for Data Requests */
std::list<TokenRequestV2> mRequests;
std::list<TokenRequestV2> mRequests;
RsTokenServiceV2 *mService;
TokenResponseV2 *mResponder;