added choice for default auto-download directory per channel.

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@6376 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2013-05-23 21:47:50 +00:00
parent 2986e81f7e
commit c2fa746991
7 changed files with 280 additions and 11 deletions

View File

@ -61,6 +61,7 @@ class ChannelInfo
uint32_t pngImageLen;
time_t lastPost;
std::string destination_directory ;
};
//! for storing a channel msgs thumbnail picture
@ -263,6 +264,10 @@ virtual void getPubKeysAvailableGrpIds(std::list<std::string>& chanIds) = 0;
*/
virtual bool channelSetAutoDl(const std::string& chId, bool autoDl) = 0;
// sets the defautl destination directory for files downloaded in this channel.
// Default is "" which means Downloads/
virtual bool channelSetDestinationDirectory(const std::string& cid,const std::string& dir) = 0 ;
/*!
* get what autoDl is set to for the given channel id

View File

@ -85,7 +85,23 @@ void RsChannelReadStatus::clear()
return;
}
std::ostream& RsChannelDestDirConfigItem::print(std::ostream &out, uint16_t indent = 0)
{
printRsItemBase(out, "RsChannelDestDirConfigItem", indent);
uint16_t int_Indent = indent + 2;
RsDistribChildConfig::print(out, int_Indent);
for(uint32_t i=0;i<dest_dirs.size();++i)
{
printIndent(out, int_Indent); out << "channel id : " << dest_dirs[i].first ;
out << ". Dir = " << dest_dirs[i].second << std::endl;
}
printRsItemEnd(out, "RsChannelDestDirConfigItem", indent);
return out;
}
std::ostream& RsChannelReadStatus::print(std::ostream &out, uint16_t indent = 0)
{
@ -257,6 +273,25 @@ RsChannelMsg *RsChannelSerialiser::deserialiseMsg(void *data, uint32_t *pktsize)
}
uint32_t RsChannelSerialiser::sizeDestDirConfig(RsChannelDestDirConfigItem *item)
{
uint32_t s = 8; /* header */
/* RsDistribChildConfig stuff */
s += 4; /* save_type */
/* RsChannelReadStatus stuff */
s += 4; /* size */
for(uint32_t i=0;i<item->dest_dirs.size();++i)
{
s += GetTlvStringSize(item->dest_dirs[i].first) ;
s += GetTlvStringSize(item->dest_dirs[i].second) ;
}
return s;
}
uint32_t RsChannelSerialiser::sizeReadStatus(RsChannelReadStatus *item)
{
uint32_t s = 8; /* header */
@ -279,6 +314,54 @@ uint32_t RsChannelSerialiser::sizeReadStatus(RsChannelReadStatus *item)
return s;
}
/* serialise the data to the buffer */
bool RsChannelSerialiser::serialiseDestDirConfig(RsChannelDestDirConfigItem *item, void *data, uint32_t *pktsize)
{
uint32_t tlvsize = sizeDestDirConfig(item);
uint32_t offset = 0;
if (*pktsize < tlvsize)
return false; /* not enough space */
*pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize);
#ifdef RSSERIAL_DEBUG
std::cerr << "RsChannelSerialiser::serialiseDestDirConfig() Header: " << ok << std::endl;
std::cerr << "RsChannelSerialiser::serialiseDestDirConfig() Size: " << tlvsize << std::endl;
#endif
/* skip the header */
offset += 8;
/* RsDistribMsg first */
ok &= setRawUInt32(data, tlvsize, &offset, item->save_type);
#ifdef RSSERIAL_DEBUG
std::cerr << "RsChannelSerialiser::serialiseDestDirConfig() save_type: " << ok << std::endl;
#endif
ok &= setRawUInt32(data, tlvsize, &offset, item->dest_dirs.size()); /* value */
for(uint32_t i=0;i<item->dest_dirs.size();++i)
{
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GROUPID, item->dest_dirs[i].first) ;
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PATH, item->dest_dirs[i].second) ;
}
#ifdef RSSERIAL_DEBUG
std::cerr << "RsChannelSerialiser::serialiseDestDirConfig() msgReadStatus: " << ok << std::endl;
#endif
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsChannelSerialiser::serialiseDestDirConfig() Size Error! " << std::endl;
}
return ok;
}
/* serialise the data to the buffer */
bool RsChannelSerialiser::serialiseReadStatus(RsChannelReadStatus *item, void *data, uint32_t *pktsize)
{
@ -337,7 +420,63 @@ bool RsChannelSerialiser::serialiseReadStatus(RsChannelReadStatus *item, voi
return ok;
}
RsChannelDestDirConfigItem *RsChannelSerialiser::deserialiseDestDirConfig(void *data, uint32_t *pktsize)
{
/* get the type and size */
uint32_t rstype = getRsItemId(data);
uint32_t rssize = getRsItemSize(data);
uint32_t offset = 0;
if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_TYPE_CHANNEL != getRsItemService(rstype)) || (RS_PKT_SUBTYPE_CHANNEL_DEST_DIR != getRsItemSubType(rstype)))
return NULL; /* wrong type */
if (*pktsize < rssize) /* check size */
return NULL; /* not enough data */
/* set the packet length */
*pktsize = rssize;
bool ok = true;
/* ready to load */
RsChannelDestDirConfigItem *item = new RsChannelDestDirConfigItem();
item->clear();
/* skip the header */
offset += 8;
/* RsDistribMsg first */
ok &= getRawUInt32(data, rssize, &offset, &(item->save_type));
uint32_t size ;
ok &= getRawUInt32(data, rssize, &offset, &size) ;
for(uint32_t i=0;i<size;++i)
{
std::string chid, path ;
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GROUPID, chid) ;
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PATH , path) ;
item->dest_dirs.push_back(std::pair<std::string,std::string>(chid,path)) ;
}
if(offset != rssize)
{
ok = false;
std::cerr << "RsChannelSerialiser::deserialiseDestDirConfig() Size Error! " << std::endl;
}
if (!ok)
{
delete item;
return NULL;
}
return item;
}
RsChannelReadStatus *RsChannelSerialiser::deserialiseReadStatus(void *data, uint32_t *pktsize)
{
@ -413,6 +552,7 @@ uint32_t RsChannelSerialiser::size(RsItem *item)
{
RsChannelMsg* dcm;
RsChannelReadStatus* drs;
RsChannelDestDirConfigItem* dd;
if( NULL != ( dcm = dynamic_cast<RsChannelMsg*>(item)))
{
@ -422,6 +562,10 @@ uint32_t RsChannelSerialiser::size(RsItem *item)
{
return sizeReadStatus(drs);
}
else if(NULL != (dd = dynamic_cast<RsChannelDestDirConfigItem* >(item)))
{
return sizeDestDirConfig(dd);
}
return false;
}
@ -430,6 +574,7 @@ bool RsChannelSerialiser::serialise(RsItem *item, void *data, uint32_t *pkts
{
RsChannelMsg* dcm;
RsChannelReadStatus* drs;
RsChannelDestDirConfigItem* dd;
if( NULL != ( dcm = dynamic_cast<RsChannelMsg*>(item)))
{
@ -439,12 +584,19 @@ bool RsChannelSerialiser::serialise(RsItem *item, void *data, uint32_t *pkts
{
return serialiseReadStatus(drs, data, pktsize);
}
else if(NULL != (dd = dynamic_cast<RsChannelDestDirConfigItem* >(item)))
{
return serialiseDestDirConfig(dd, data, pktsize);
}
return false;
}
RsItem *RsChannelSerialiser::deserialise(void *data, uint32_t *pktsize)
{
if(data == NULL)
return NULL ;
/* get the type and size */
uint32_t rstype = getRsItemId(data);
@ -460,6 +612,8 @@ RsItem *RsChannelSerialiser::deserialise(void *data, uint32_t *pktsize)
return deserialiseMsg(data, pktsize);
case RS_PKT_SUBTYPE_CHANNEL_READ_STATUS:
return deserialiseReadStatus(data, pktsize);
case RS_PKT_SUBTYPE_CHANNEL_DEST_DIR:
return deserialiseDestDirConfig(data, pktsize);
default:
return NULL;
}

View File

@ -37,6 +37,7 @@
const uint8_t RS_PKT_SUBTYPE_CHANNEL_MSG = 0x01;
const uint8_t RS_PKT_SUBTYPE_CHANNEL_READ_STATUS = 0x02;
const uint8_t RS_PKT_SUBTYPE_CHANNEL_DEST_DIR = 0x03;
/**************************************************************************/
@ -85,8 +86,25 @@ public:
/// a map which contains the read for messages within a forum
std::map<std::string, uint32_t> msgReadStatus;
std::string destination_directory ;
};
/*!
* This is used to store the destination directories of each channel
*/
class RsChannelDestDirConfigItem : public RsDistribChildConfig
{
public:
RsChannelDestDirConfigItem()
: RsDistribChildConfig(RS_SERVICE_TYPE_CHANNEL, RS_PKT_SUBTYPE_CHANNEL_DEST_DIR)
{ return; }
virtual ~RsChannelDestDirConfigItem() {}
virtual void clear() { dest_dirs.clear() ; }
virtual std::ostream& print(std::ostream &out, uint16_t indent);
std::vector<std::pair<std::string, std::string> > dest_dirs;
};
class RsChannelSerialiser: public RsSerialType
{
public:
@ -111,6 +129,9 @@ virtual uint32_t sizeReadStatus(RsChannelReadStatus* );
virtual bool serialiseReadStatus(RsChannelReadStatus* item, void* data, uint32_t *size);
virtual RsChannelReadStatus *deserialiseReadStatus(void* data, uint32_t *size);
virtual uint32_t sizeDestDirConfig(RsChannelDestDirConfigItem* );
virtual bool serialiseDestDirConfig(RsChannelDestDirConfigItem* item, void* data, uint32_t *size);
virtual RsChannelDestDirConfigItem *deserialiseDestDirConfig(void* data, uint32_t *size);
};
/**************************************************************************/

View File

@ -117,6 +117,7 @@ bool p3Channels::getChannelInfo(const std::string &cId, ChannelInfo &ci)
ci.pop = gi->sources.size();
ci.lastPost = gi->lastPost;
ci.destination_directory = (mDestinationDirectories.find(cId)==mDestinationDirectories.end())?"":(mDestinationDirectories[cId]) ;
ci.pngChanImage = gi->grpIcon.pngImageData;
@ -666,6 +667,16 @@ void p3Channels::getPubKeysAvailableGrpIds(std::list<std::string>& grpIds)
}
bool p3Channels::channelSetDestinationDirectory(const std::string& chId, const std::string& dest_dir)
{
RsStackMutex stack(distribMtx);
mDestinationDirectories[chId] = dest_dir ;
IndicateConfigChanged() ;
return true ;
}
bool p3Channels::channelSetAutoDl(const std::string& chId, bool autoDl)
{
@ -988,18 +999,28 @@ void p3Channels::locked_notifyGroupChanged(GroupInfo &grp, uint32_t flags, bool
bool p3Channels::childLoadList(std::list<RsItem* >& configSaves)
{
RsChannelReadStatus* drs = NULL;
std::list<RsItem* >::iterator it;
RsChannelDestDirConfigItem *dd = NULL ;
for(it = configSaves.begin(); it != configSaves.end(); it++)
for(std::list<RsItem* >::iterator it = configSaves.begin(); it != configSaves.end(); it++)
{
if(NULL != (drs = dynamic_cast<RsChannelReadStatus* >(*it)))
processChanReadStatus(drs); // don't delete, since it's used later on.
else if(NULL != (dd = dynamic_cast<RsChannelDestDirConfigItem*>(*it)))
{
processChanReadStatus(drs);
mDestinationDirectories.clear() ;
for(uint32_t i=0;i<dd->dest_dirs.size();++i)
{
mDestinationDirectories[dd->dest_dirs[i].first] = dd->dest_dirs[i].second ;
std::cerr << "p3Channels: setDestination directory or ChId " << dd->dest_dirs[i].first << " to " << dd->dest_dirs[i].second <<std::endl;
}
delete *it ;
}
else
{
std::cerr << "p3Channels::childLoadList(): Configs items loaded were incorrect!"
<< std::endl;
std::cerr << "p3Channels::childLoadList(): Configs items loaded were incorrect!" << std::endl;
if(*it != NULL)
delete *it;
@ -1011,9 +1032,8 @@ bool p3Channels::childLoadList(std::list<RsItem* >& configSaves)
void p3Channels::processChanReadStatus(RsChannelReadStatus* drs)
{
// mReadStatus.push_back(drs);
mReadStatus.push_back(drs);
std::string chId = drs->channelId;
statMap::iterator sit = drs->msgReadStatus.find(chId);
@ -1030,13 +1050,10 @@ void p3Channels::processChanReadStatus(RsChannelReadStatus* drs)
mReadStatus.push_back(drs);
saveList.push_back(drs);
}
std::list<RsItem *> p3Channels::childSaveList()
{
std::list<RsChannelReadStatus* >::iterator lit = mReadStatus.begin();
statMap::iterator sit, mit;
@ -1057,7 +1074,17 @@ std::list<RsItem *> p3Channels::childSaveList()
}
}
return saveList;
// Make a copy of saveList and add additional items we want to save.
//
std::list<RsItem*> to_return = saveList ;
RsChannelDestDirConfigItem *dd = new RsChannelDestDirConfigItem ;
for(std::map<std::string,std::string>::const_iterator it(mDestinationDirectories.begin());it!=mDestinationDirectories.end();++it)
dd->dest_dirs.push_back(*it) ;
to_return.push_back(dd) ;
return to_return;
}
/****************************************/

View File

@ -85,6 +85,7 @@ virtual bool channelEditInfo(const std::string &chId, ChannelInfo &ci);
virtual void getPubKeysAvailableGrpIds(std::list<std::string>& grpIds);
virtual bool channelSetAutoDl(const std::string& chId, bool autoDl);
virtual bool channelGetAutoDl(const std::string& chId, bool& autoDl);
virtual bool channelSetDestinationDirectory(const std::string& chId,const std::string& dest_dir) ;
/***************************************************************************************/
/****************** Event Feedback (Overloaded form p3distrib) *************************/
@ -123,6 +124,7 @@ void removeChannelReadStatusEntry(const std::string& cId);
chanStatMap mMsgReadStatus;
statMap mChannelStatus;
std::map<std::string,std::string> mDestinationDirectories ;
};

View File

@ -21,6 +21,7 @@
#include <QMenu>
#include <QTimer>
#include <QFile>
#include <QStandardItemModel>
#include <QMessageBox>
@ -29,6 +30,8 @@
#include <set>
#include <map>
#include <retroshare/rsfiles.h>
#include "ChannelFeed.h"
#include "feeds/ChanMsgItem.h"
@ -197,6 +200,51 @@ void ChannelFeed::channelListCustomPopupMenu( QPoint /*point*/ )
contextMnu.addAction( shareKeyAct );
}
if(ci.channelFlags & RS_DISTRIB_SUBSCRIBED)
{
QMenu *directoryMenu = contextMnu.addMenu(QIcon(":/images/folderopen.png"),tr("Set destination directory")) ;
QAction *specifyDestinationDirectoryAct = new QAction(QIcon(":/images/filefind.png"), tr("Other..."), &contextMnu);
directoryMenu->addAction(specifyDestinationDirectoryAct);
// Now get the list of existing directories.
std::list<SharedDirInfo> dirs ;
rsFiles->getSharedDirectories(dirs) ;
bool found = false ;
for(std::list<SharedDirInfo>::const_iterator it(dirs.begin());it!=dirs.end();++it)
{
// check for existence of directory name
QFile directory(QString::fromUtf8((*it).filename.c_str())) ;
if(!directory.exists()) continue ;
if(!(directory.permissions() & QFile::WriteOwner)) continue ;
QAction *act ;
if(ci.destination_directory == (*it).filename)
{
act = new QAction(QIcon(":/images/start.png"),QString::fromUtf8((*it).virtualname.c_str()),directoryMenu) ;
found = true ;
}
else
act = new QAction(QString::fromUtf8((*it).virtualname.c_str()),directoryMenu) ;
act->setData(QString::fromUtf8((*it).filename.c_str())) ;
connect(act,SIGNAL(triggered()),this,SLOT(setDestinationDirectory())) ;
directoryMenu->addAction(act) ;
}
QAction *defaultDestinationDirectoryAct = new QAction(tr("[Default]"), &contextMnu);
defaultDestinationDirectoryAct->setData(QString()) ;
connect(defaultDestinationDirectoryAct,SIGNAL(triggered()),this,SLOT(setDestinationDirectory())) ;
directoryMenu->addAction(defaultDestinationDirectoryAct);
if(!found)
defaultDestinationDirectoryAct->setIcon(QIcon(":/images/start.png")) ;
}
if(ci.channelFlags & RS_DISTRIB_SUBSCRIBED)
{
contextMnu.addAction( unsubscribechannelAct );
@ -220,6 +268,17 @@ void ChannelFeed::channelListCustomPopupMenu( QPoint /*point*/ )
contextMnu.exec(QCursor::pos());
}
void ChannelFeed::setDestinationDirectory()
{
ChannelInfo ci;
if (!rsChannels->getChannelInfo(mChannelId, ci))
return;
std::string dest_dir(qobject_cast<QAction*>(sender())->data().toString().toUtf8().data()) ;
std::cerr << "Setting new directory " << dest_dir << " to channel " << mChannelId << std::endl;
rsChannels->channelSetDestinationDirectory(mChannelId,dest_dir) ;
}
void ChannelFeed::createChannel()
{

View File

@ -79,6 +79,7 @@ private slots:
void editChannelDetail();
void shareKey();
void copyChannelLink();
void setDestinationDirectory();
void channelMsgReadSatusChanged(const QString& channelId, const QString& msgId, int status);