diff --git a/libretroshare/src/gxs/rsgenexchange.h b/libretroshare/src/gxs/rsgenexchange.h index 94a455824..677d1d963 100644 --- a/libretroshare/src/gxs/rsgenexchange.h +++ b/libretroshare/src/gxs/rsgenexchange.h @@ -915,7 +915,6 @@ private: std::vector mMsgDeletePublish; std::map > mRoutingClues ; - std::list > mTrackingClues ; }; #endif // RSGENEXCHANGE_H diff --git a/libretroshare/src/rsitems/rsserviceids.h b/libretroshare/src/rsitems/rsserviceids.h index e3fc4a298..557bc54d7 100644 --- a/libretroshare/src/rsitems/rsserviceids.h +++ b/libretroshare/src/rsitems/rsserviceids.h @@ -84,6 +84,9 @@ const uint16_t RS_SERVICE_GXS_TYPE_REPUTATION = 0x0219; const uint16_t RS_SERVICE_TYPE_GXS_RECOGN = 0x0220; const uint16_t RS_SERVICE_TYPE_GXS_TRANS = 0x0230; +const uint16_t RS_SERVICE_GXS_TYPE_FORUMS_CONFIG = 0x0315; +const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG = 0x0317; + // Experimental Services. /* DSDV Testing at the moment - Service Only */ const uint16_t RS_SERVICE_TYPE_DSDV = 0x1010; diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index 6f0b668b5..0d9300202 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -1649,7 +1649,9 @@ int RsServer::StartupRetroShare() mConfigMgr->addConfiguration("identity.cfg", gxsid_ns); mConfigMgr->addConfiguration("gxsforums.cfg", gxsforums_ns); + mConfigMgr->addConfiguration("gxsforums_srv.cfg", mGxsForums); mConfigMgr->addConfiguration("gxschannels.cfg", gxschannels_ns); + mConfigMgr->addConfiguration("gxschannels_srv.cfg", mGxsChannels); mConfigMgr->addConfiguration("gxscircles.cfg", gxscircles_ns); mConfigMgr->addConfiguration("posted.cfg", posted_ns); #ifdef RS_USE_WIKI diff --git a/libretroshare/src/services/p3gxschannels.cc b/libretroshare/src/services/p3gxschannels.cc index 6805bb0ab..d2578d470 100644 --- a/libretroshare/src/services/p3gxschannels.cc +++ b/libretroshare/src/services/p3gxschannels.cc @@ -120,6 +120,92 @@ uint32_t p3GxsChannels::channelsAuthenPolicy() return policy; } +static const uint32_t GXS_CHANNELS_CONFIG_MAX_TIME_NOTIFY_STORAGE = 86400*30*2 ; // ignore notifications for 2 months +static const uint8_t GXS_CHANNELS_CONFIG_SUBTYPE_NOTIFY_RECORD = 0x01 ; + +struct RsGxsForumNotifyRecordsItem: public RsItem +{ + + RsGxsForumNotifyRecordsItem() + : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG,GXS_CHANNELS_CONFIG_SUBTYPE_NOTIFY_RECORD) + {} + + virtual ~RsGxsForumNotifyRecordsItem() {} + + void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) + { + RS_REGISTER_SERIAL_MEMBER(records); + } + void clear() {} + + std::map records; +}; + +class GxsChannelsConfigSerializer : public RsServiceSerializer +{ +public: + GxsChannelsConfigSerializer() : RsServiceSerializer(RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG) {} + virtual ~GxsChannelsConfigSerializer() {} + + RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const + { + if(service_id != RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG) + return NULL; + + switch(item_sub_id) + { + case GXS_CHANNELS_CONFIG_SUBTYPE_NOTIFY_RECORD: return new RsGxsForumNotifyRecordsItem(); + default: + return NULL; + } + } +}; + +bool p3GxsChannels::saveList(bool &cleanup, std::list&saveList) +{ + cleanup = true ; + + RsGxsForumNotifyRecordsItem *item = new RsGxsForumNotifyRecordsItem ; + + item->records = mKnownChannels ; + + saveList.push_back(item) ; + return true; +} + +bool p3GxsChannels::loadList(std::list& loadList) +{ + while(!loadList.empty()) + { + RsItem *item = loadList.front(); + loadList.pop_front(); + + time_t now = time(NULL); + + RsGxsForumNotifyRecordsItem *fnr = dynamic_cast(item) ; + + if(fnr != NULL) + { + mKnownChannels.clear(); + + for(auto it(fnr->records.begin());it!=fnr->records.end();++it) + if( it->second + GXS_CHANNELS_CONFIG_MAX_TIME_NOTIFY_STORAGE < now) + mKnownChannels.insert(*it) ; + } + + delete item ; + } + return true; +} + +RsSerialiser* p3GxsChannels::setupSerialiser() +{ + RsSerialiser* rss = new RsSerialiser; + rss->addSerialType(new GxsChannelsConfigSerializer()); + + return rss; +} + /** Overloaded to cache new groups **/ RsGenExchange::ServiceCreate_Return p3GxsChannels::service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& /* keySet */) @@ -223,7 +309,7 @@ void p3GxsChannels::notifyChanges(std::vector &changes) if(mKnownChannels.find(*git) == mKnownChannels.end()) { notify->AddFeedItem(RS_FEED_ITEM_CHANNEL_NEW, git->toStdString()); - mKnownChannels.insert(*git) ; + mKnownChannels.insert(std::make_pair(*git,time(NULL))) ; } else std::cerr << "(II) Not notifying already known channel " << *git << std::endl; diff --git a/libretroshare/src/services/p3gxschannels.h b/libretroshare/src/services/p3gxschannels.h index db73448cd..4eb5f5fba 100644 --- a/libretroshare/src/services/p3gxschannels.h +++ b/libretroshare/src/services/p3gxschannels.h @@ -55,7 +55,7 @@ class SSGxsChannelGroup class p3GxsChannels: public RsGenExchange, public RsGxsChannels, - public GxsTokenQueue, + public GxsTokenQueue, public p3Config, public RsTickEvent /* only needed for testing - remove after */ { public: @@ -68,6 +68,10 @@ virtual void service_tick(); protected: + virtual RsSerialiser* setupSerialiser(); // @see p3Config::setupSerialiser() + virtual bool saveList(bool &cleanup, std::list&saveList); // @see p3Config::saveList(bool &cleanup, std::list&) + virtual bool loadList(std::list& loadList); // @see p3Config::loadList(std::list&) + // Overloaded to cache new groups. virtual RsGenExchange::ServiceCreate_Return service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet); @@ -218,7 +222,7 @@ bool generateGroup(uint32_t &token, std::string groupName); RsGxsMessageId mGenThreadId; p3GxsCommentService *mCommentService; - std::set mKnownChannels; + std::map mKnownChannels; }; #endif diff --git a/libretroshare/src/services/p3gxsforums.cc b/libretroshare/src/services/p3gxsforums.cc index a64e547b8..dd98f88d1 100644 --- a/libretroshare/src/services/p3gxsforums.cc +++ b/libretroshare/src/services/p3gxsforums.cc @@ -95,6 +95,91 @@ uint32_t p3GxsForums::forumsAuthenPolicy() return policy; } +static const uint32_t GXS_FORUMS_CONFIG_MAX_TIME_NOTIFY_STORAGE = 86400*30*2 ; // ignore notifications for 2 months +static const uint8_t GXS_FORUMS_CONFIG_SUBTYPE_NOTIFY_RECORD = 0x01 ; + +struct RsGxsForumNotifyRecordsItem: public RsItem +{ + + RsGxsForumNotifyRecordsItem() + : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_GXS_TYPE_FORUMS_CONFIG,GXS_FORUMS_CONFIG_SUBTYPE_NOTIFY_RECORD) + {} + + virtual ~RsGxsForumNotifyRecordsItem() {} + + void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) + { + RS_REGISTER_SERIAL_MEMBER(records); + } + void clear() {} + + std::map records; +}; + +class GxsForumsConfigSerializer : public RsServiceSerializer +{ +public: + GxsForumsConfigSerializer() : RsServiceSerializer(RS_SERVICE_GXS_TYPE_FORUMS_CONFIG) {} + virtual ~GxsForumsConfigSerializer() {} + + RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const + { + if(service_id != RS_SERVICE_GXS_TYPE_FORUMS_CONFIG) + return NULL; + + switch(item_sub_id) + { + case GXS_FORUMS_CONFIG_SUBTYPE_NOTIFY_RECORD: return new RsGxsForumNotifyRecordsItem(); + default: + return NULL; + } + } +}; + +bool p3GxsForums::saveList(bool &cleanup, std::list&saveList) +{ + cleanup = true ; + + RsGxsForumNotifyRecordsItem *item = new RsGxsForumNotifyRecordsItem ; + + item->records = mKnownForums ; + + saveList.push_back(item) ; + return true; +} + +bool p3GxsForums::loadList(std::list& loadList) +{ + while(!loadList.empty()) + { + RsItem *item = loadList.front(); + loadList.pop_front(); + + time_t now = time(NULL); + + RsGxsForumNotifyRecordsItem *fnr = dynamic_cast(item) ; + + if(fnr != NULL) + { + mKnownForums.clear(); + + for(auto it(fnr->records.begin());it!=fnr->records.end();++it) + if( it->second + GXS_FORUMS_CONFIG_MAX_TIME_NOTIFY_STORAGE < now) + mKnownForums.insert(*it) ; + } + + delete item ; + } + return true; +} + +RsSerialiser* p3GxsForums::setupSerialiser() +{ + RsSerialiser* rss = new RsSerialiser; + rss->addSerialType(new GxsForumsConfigSerializer()); + + return rss; +} void p3GxsForums::notifyChanges(std::vector &changes) { @@ -145,7 +230,9 @@ void p3GxsForums::notifyChanges(std::vector &changes) if(mKnownForums.find(*git) == mKnownForums.end()) { notify->AddFeedItem(RS_FEED_ITEM_FORUM_NEW, git->toStdString()); - mKnownForums.insert(*git) ; + mKnownForums.insert(std::make_pair(*git,time(NULL))) ; + + IndicateConfigChanged(); } else std::cerr << "(II) Not notifying already known forum " << *git << std::endl; @@ -584,4 +671,3 @@ void p3GxsForums::handle_event(uint32_t event_type, const std::string &/*elabel* break; } } - diff --git a/libretroshare/src/services/p3gxsforums.h b/libretroshare/src/services/p3gxsforums.h index 1e2e78d92..a4e0ebf47 100644 --- a/libretroshare/src/services/p3gxsforums.h +++ b/libretroshare/src/services/p3gxsforums.h @@ -39,7 +39,7 @@ * */ -class p3GxsForums: public RsGenExchange, public RsGxsForums, +class p3GxsForums: public RsGenExchange, public RsGxsForums, public p3Config, public RsTickEvent /* only needed for testing - remove after */ { public: @@ -58,6 +58,10 @@ virtual void notifyChanges(std::vector& changes); // Overloaded from RsTickEvent. virtual void handle_event(uint32_t event_type, const std::string &elabel); + virtual RsSerialiser* setupSerialiser(); // @see p3Config::setupSerialiser() + virtual bool saveList(bool &cleanup, std::list&saveList); // @see p3Config::saveList(bool &cleanup, std::list&) + virtual bool loadList(std::list& loadList); // @see p3Config::loadList(std::list&) + public: virtual bool getGroupData(const uint32_t &token, std::vector &groups); @@ -117,7 +121,7 @@ bool generateGroup(uint32_t &token, std::string groupName); int mGenCount; std::vector mGenRefs; RsGxsMessageId mGenThreadId; - std::set mKnownForums ; + std::map mKnownForums ; }; diff --git a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp index 8f7cb20be..26e609289 100644 --- a/retroshare-gui/src/gui/common/RsCollectionDialog.cpp +++ b/retroshare-gui/src/gui/common/RsCollectionDialog.cpp @@ -21,17 +21,23 @@ * Boston, MA 02110-1301, USA. ****************************************************************/ +#include "RsCollectionDialog.h" + +#include "RsCollection.h" +#include "util/misc.h" + #include +#include +#include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include "RsCollectionDialog.h" -#include "RsCollection.h" -#include "util/misc.h" +#include + #define COLUMN_FILE 0 #define COLUMN_FILEPATH 1 #define COLUMN_SIZE 2 @@ -366,6 +372,8 @@ void RsCollectionDialog::processSettings(bool bLoad) ui._listSplitter->restoreState(Settings->value("ListSplitterState_CM").toByteArray()); // Load system file header configuration ui._systemFileTW->header()->restoreState(Settings->value("SystemFileHeader_CM").toByteArray()); + // Load file entries header configuration + ui._fileEntriesTW->header()->restoreState(Settings->value("FileEntriesHeader_CM").toByteArray()); } else { // Load windows geometrie restoreGeometry(Settings->value("WindowGeometrie").toByteArray()); @@ -374,22 +382,30 @@ void RsCollectionDialog::processSettings(bool bLoad) ui._listSplitter->restoreState(Settings->value("ListSplitterState").toByteArray()); // Load system file header configuration ui._systemFileTW->header()->restoreState(Settings->value("SystemFileHeader").toByteArray()); + // Load file entries header configuration + ui._fileEntriesTW->header()->restoreState(Settings->value("FileEntriesHeader").toByteArray()); } } else { if(_creationMode && !_readOnly){ // Save windows geometrie Settings->setValue("WindowGeometrie_CM",saveGeometry()); - // Save splitter state - Settings->setValue("SplitterState_CM", ui._listSplitter->saveState()); - // Save treeView header configuration + // Save splitters state + Settings->setValue("MainSplitterState_CM", ui._mainSplitter->saveState()); + Settings->setValue("ListSplitterState_CM", ui._listSplitter->saveState()); + // Save system file header configuration Settings->setValue("SystemFileHeader_CM", ui._systemFileTW->header()->saveState()); + // Save file entries header configuration + Settings->setValue("FileEntriesHeader_CM", ui._fileEntriesTW->header()->saveState()); } else { // Save windows geometrie Settings->setValue("WindowGeometrie",saveGeometry()); // Save splitter state - Settings->setValue("SplitterState", ui._listSplitter->saveState()); - // Save treeView header configuration + Settings->setValue("MainSplitterState", ui._mainSplitter->saveState()); + Settings->setValue("ListSplitterState", ui._listSplitter->saveState()); + // Save system file header configuration Settings->setValue("SystemFileHeader", ui._systemFileTW->header()->saveState()); + // Save file entries header configuration + Settings->setValue("FileEntriesHeader", ui._fileEntriesTW->header()->saveState()); } } @@ -797,7 +813,7 @@ void RsCollectionDialog::addRecursive(bool recursive) for (QHash::Iterator it = _listOfFilesAddedInDir.begin(); it != _listOfFilesAddedInDir.end() ; ++it) { QString path = it.value(); - it.value() = ""; + //it.value() = "";//Don't reset value, could be an older attachment not terminated. if (dirToAdd.contains(path)){ it.value() = dirToAdd.value(path); } else if(item) { @@ -980,7 +996,11 @@ bool RsCollectionDialog::removeItem(QTreeWidgetItem *item, bool &removeOnlyFile) //First uncheck item to update parent informations item->setCheckState(COLUMN_FILE,Qt::Unchecked); QTreeWidgetItem *parent = item->parent(); - parent->removeChild(item); + if (parent) { + parent->removeChild(item); + } else { + getRootItem()->removeChild(item); + } return true; } else { if (!removeOnlyFile) {