diff --git a/libretroshare/src/retroshare/rsiface.h b/libretroshare/src/retroshare/rsiface.h index 0db791373..3a5ef4b78 100644 --- a/libretroshare/src/retroshare/rsiface.h +++ b/libretroshare/src/retroshare/rsiface.h @@ -216,19 +216,20 @@ class NotifyBase virtual std::string askForPassword(const std::string& /* key_details */ ,bool /* prev_is_bad */ ) { return "" ;} }; -const int NOTIFY_LIST_NEIGHBOURS = 1; -const int NOTIFY_LIST_FRIENDS = 2; -const int NOTIFY_LIST_SEARCHLIST = 4; -const int NOTIFY_LIST_MESSAGELIST = 5; -const int NOTIFY_LIST_CHANNELLIST = 6; -const int NOTIFY_LIST_TRANSFERLIST = 7; -const int NOTIFY_LIST_CONFIG = 8; -const int NOTIFY_LIST_DIRLIST_LOCAL = 9; -const int NOTIFY_LIST_DIRLIST_FRIENDS = 10; -const int NOTIFY_LIST_FORUMLIST_LOCKED = 11; // use connect with Qt::QueuedConnection -const int NOTIFY_LIST_MESSAGE_TAGS = 12; -const int NOTIFY_LIST_PUBLIC_CHAT = 13; -const int NOTIFY_LIST_PRIVATE_CHAT = 14; +const int NOTIFY_LIST_NEIGHBOURS = 1; +const int NOTIFY_LIST_FRIENDS = 2; +const int NOTIFY_LIST_SEARCHLIST = 4; +const int NOTIFY_LIST_MESSAGELIST = 5; +const int NOTIFY_LIST_CHANNELLIST = 6; +const int NOTIFY_LIST_TRANSFERLIST = 7; +const int NOTIFY_LIST_CONFIG = 8; +const int NOTIFY_LIST_DIRLIST_LOCAL = 9; +const int NOTIFY_LIST_DIRLIST_FRIENDS = 10; +const int NOTIFY_LIST_FORUMLIST_LOCKED = 11; // use connect with Qt::QueuedConnection +const int NOTIFY_LIST_MESSAGE_TAGS = 12; +const int NOTIFY_LIST_PUBLIC_CHAT = 13; +const int NOTIFY_LIST_PRIVATE_INCOMING_CHAT = 14; +const int NOTIFY_LIST_PRIVATE_OUTGOING_CHAT = 15; const int NOTIFY_TYPE_SAME = 0x01; const int NOTIFY_TYPE_MOD = 0x02; /* general purpose, check all */ diff --git a/libretroshare/src/retroshare/rsmsgs.h b/libretroshare/src/retroshare/rsmsgs.h index 275a13ccc..773529167 100644 --- a/libretroshare/src/retroshare/rsmsgs.h +++ b/libretroshare/src/retroshare/rsmsgs.h @@ -177,10 +177,12 @@ virtual bool resetMessageStandardTagTypes(MsgTagType& tags) = 0; /* Chat */ virtual bool sendPublicChat(std::wstring msg) = 0; virtual bool sendPrivateChat(std::string id, std::wstring msg) = 0; -virtual int getChatQueueCount(bool privateQueue) = 0; +virtual int getPublicChatQueueCount() = 0; virtual bool getPublicChatQueue(std::list &chats) = 0; -virtual bool getPrivateChatQueueIds(std::list &ids) = 0; -virtual bool getPrivateChatQueue(std::string id, std::list &chats) = 0; +virtual int getPrivateChatQueueCount(bool incoming) = 0; +virtual bool getPrivateChatQueueIds(bool incoming, std::list &ids) = 0; +virtual bool getPrivateChatQueue(bool incoming, std::string id, std::list &chats) = 0; +virtual bool clearPrivateChatQueue(bool incoming, std::string id) = 0; virtual void sendStatusString(const std::string& id,const std::string& status_string) = 0 ; virtual void sendGroupChatStatusString(const std::string& status_string) = 0 ; diff --git a/libretroshare/src/rsserver/p3msgs.cc b/libretroshare/src/rsserver/p3msgs.cc index 9f2bf212c..d877c7fd6 100644 --- a/libretroshare/src/rsserver/p3msgs.cc +++ b/libretroshare/src/rsserver/p3msgs.cc @@ -156,9 +156,9 @@ void p3Msgs::sendStatusString(const std::string& peer_id,const std::string& stat mChatSrv->sendStatusString(peer_id,status_string); } -int p3Msgs::getChatQueueCount(bool privateQueue) +int p3Msgs::getPublicChatQueueCount() { - return mChatSrv->getChatQueueCount(privateQueue); + return mChatSrv->getPublicChatQueueCount(); } bool p3Msgs::getPublicChatQueue(std::list &chats) @@ -166,14 +166,24 @@ bool p3Msgs::getPublicChatQueue(std::list &chats) return mChatSrv->getPublicChatQueue(chats); } -bool p3Msgs::getPrivateChatQueueIds(std::list &ids) +int p3Msgs::getPrivateChatQueueCount(bool incoming) { - return mChatSrv->getPrivateChatQueueIds(ids); + return mChatSrv->getPrivateChatQueueCount(incoming); } -bool p3Msgs::getPrivateChatQueue(std::string id, std::list &chats) +bool p3Msgs::getPrivateChatQueueIds(bool incoming, std::list &ids) { - return mChatSrv->getPrivateChatQueue(id, chats); + return mChatSrv->getPrivateChatQueueIds(incoming, ids); +} + +bool p3Msgs::getPrivateChatQueue(bool incoming, std::string id, std::list &chats) +{ + return mChatSrv->getPrivateChatQueue(incoming, id, chats); +} + +bool p3Msgs::clearPrivateChatQueue(bool incoming, std::string id) +{ + return mChatSrv->clearPrivateChatQueue(incoming, id); } void p3Msgs::getOwnAvatarData(unsigned char *& data,int& size) diff --git a/libretroshare/src/rsserver/p3msgs.h b/libretroshare/src/rsserver/p3msgs.h index d9b926116..b1653cddc 100644 --- a/libretroshare/src/rsserver/p3msgs.h +++ b/libretroshare/src/rsserver/p3msgs.h @@ -119,23 +119,35 @@ class p3Msgs: public RsMsgs * returns the count of messages in public or private queue * @param public or private queue */ - virtual int getChatQueueCount(bool privateQueue); + virtual int getPublicChatQueueCount(); /*! * @param chats ref to list of received public chats is stored here */ virtual bool getPublicChatQueue(std::list &chats); + /*! + * returns the count of messages in private queue + * @param public or private queue + */ + virtual int getPrivateChatQueueCount(bool incoming); + /*! * @param id's of available private chat messages */ - virtual bool getPrivateChatQueueIds(std::list &ids); + virtual bool getPrivateChatQueueIds(bool incoming, std::list &ids); /*! * @param chats ref to list of received private chats is stored here */ - virtual bool getPrivateChatQueue(std::string id, std::list &chats); + virtual bool getPrivateChatQueue(bool incoming, std::string id, std::list &chats); + + /*! + * @param clear private chat queue + */ + virtual bool clearPrivateChatQueue(bool incoming, std::string id); + /*! * sends immediate status string to a specific peer, e.g. in a private chat * @param peer_id peer to send status string to diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index 94ea61a84..4968a3f5e 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -2302,6 +2302,7 @@ int RsServer::StartupRetroShare() #ifndef MINIMAL_LIBRS mConnMgr->addMonitor(msgSrv); mConnMgr->addMonitor(mStatusSrv); + mConnMgr->addMonitor(chatSrv); #endif // MINIMAL_LIBRS /* must also add the controller as a Monitor... diff --git a/libretroshare/src/serialiser/rsmsgitems.cc b/libretroshare/src/serialiser/rsmsgitems.cc index c1727b8f5..df39a8be3 100644 --- a/libretroshare/src/serialiser/rsmsgitems.cc +++ b/libretroshare/src/serialiser/rsmsgitems.cc @@ -56,6 +56,31 @@ std::ostream& RsChatMsgItem::print(std::ostream &out, uint16_t indent) return out; } +std::ostream& RsPrivateChatMsgConfigItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsPrivateChatMsgConfigItem", indent); + uint16_t int_Indent = indent + 2; + + out << "peerId: " << configPeerId << std::endl; + + printIndent(out, int_Indent); + out << "QblogMs " << chatFlags << std::endl; + + printIndent(out, int_Indent); + out << "QblogMs " << configFlags << std::endl; + + printIndent(out, int_Indent); + out << "sendTime: " << sendTime << std::endl; + + printIndent(out, int_Indent); + + std::string cnv_message(message.begin(), message.end()); + out << "msg: " << cnv_message << std::endl; + + printRsItemEnd(out, "RsPrivateChatMsgConfigItem", indent); + return out; +} + std::ostream& RsChatStatusItem::print(std::ostream &out, uint16_t indent) { printRsItemBase(out, "RsChatStatusItem", indent); @@ -110,9 +135,10 @@ RsItem *RsChatSerialiser::deserialise(void *data, uint32_t *pktsize) switch(getRsItemSubType(rstype)) { - case RS_PKT_SUBTYPE_DEFAULT: return new RsChatMsgItem(data,*pktsize) ; - case RS_PKT_SUBTYPE_CHAT_STATUS: return new RsChatStatusItem(data,*pktsize) ; - case RS_PKT_SUBTYPE_CHAT_AVATAR: return new RsChatAvatarItem(data,*pktsize) ; + case RS_PKT_SUBTYPE_DEFAULT: return new RsChatMsgItem(data,*pktsize) ; + case RS_PKT_SUBTYPE_PRIVATECHATMSG_CONFIG: return new RsPrivateChatMsgConfigItem(data,*pktsize) ; + case RS_PKT_SUBTYPE_CHAT_STATUS: return new RsChatStatusItem(data,*pktsize) ; + case RS_PKT_SUBTYPE_CHAT_AVATAR: return new RsChatAvatarItem(data,*pktsize) ; default: std::cerr << "Unknown packet type in chat!" << std::endl ; return NULL ; @@ -129,6 +155,19 @@ uint32_t RsChatMsgItem::serial_size() return s; } +uint32_t RsPrivateChatMsgConfigItem::serial_size() +{ + uint32_t s = 8; /* header */ + s += GetTlvStringSize(configPeerId); + s += 4; /* chatFlags */ + s += 4; /* configFlags */ + s += 4; /* sendTime */ + s += GetTlvWideStringSize(message); + s += 4; /* recvTime */ + + return s; +} + uint32_t RsChatStatusItem::serial_size() { uint32_t s = 8; /* header */ @@ -198,6 +237,47 @@ bool RsChatMsgItem::serialise(void *data, uint32_t& pktsize) return ok; } +bool RsPrivateChatMsgConfigItem::serialise(void *data, uint32_t& pktsize) +{ + uint32_t tlvsize = serial_size() ; + uint32_t offset = 0; + + if (pktsize < tlvsize) + return false; /* not enough space */ + + pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, PacketId(), tlvsize); + +#ifdef CHAT_DEBUG + std::cerr << "RsChatSerialiser::serialiseItem() Header: " << ok << std::endl; + std::cerr << "RsChatSerialiser::serialiseItem() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PEERID, configPeerId); + ok &= setRawUInt32(data, tlvsize, &offset, chatFlags); + ok &= setRawUInt32(data, tlvsize, &offset, configFlags); + ok &= setRawUInt32(data, tlvsize, &offset, sendTime); + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_MSG, message); + ok &= setRawUInt32(data, tlvsize, &offset, recvTime); + + if (offset != tlvsize) + { + ok = false; +#ifdef CHAT_DEBUG + std::cerr << "RsChatSerialiser::serialiseItem() Size Error! " << std::endl; +#endif + } + + return ok; +} + bool RsChatStatusItem::serialise(void *data, uint32_t& pktsize) { uint32_t tlvsize = serial_size() ; @@ -302,6 +382,53 @@ RsChatMsgItem::RsChatMsgItem(void *data,uint32_t size) std::cerr << "Unknown error while deserializing." << std::endl ; } +RsPrivateChatMsgConfigItem::RsPrivateChatMsgConfigItem(void *data,uint32_t size) + : RsChatItem(RS_PKT_SUBTYPE_PRIVATECHATMSG_CONFIG) +{ + uint32_t offset = 8; // skip the header + uint32_t rssize = getRsItemSize(data); + bool ok = true ; + + /* get mandatory parts first */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PEERID, configPeerId); + ok &= getRawUInt32(data, rssize, &offset, &chatFlags); + ok &= getRawUInt32(data, rssize, &offset, &configFlags); + ok &= getRawUInt32(data, rssize, &offset, &sendTime); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_MSG, message); + ok &= getRawUInt32(data, rssize, &offset, &recvTime); + +#ifdef CHAT_DEBUG + std::cerr << "Building new chat msg config item." << std::endl ; +#endif + if (offset != rssize) + std::cerr << "Size error while deserializing." << std::endl ; + if (!ok) + std::cerr << "Unknown error while deserializing." << std::endl ; +} + +/* set data from RsChatMsgItem to RsPrivateChatMsgConfigItem */ +void RsPrivateChatMsgConfigItem::set(RsChatMsgItem *ci, const std::string &peerId, uint32_t confFlags) +{ + PeerId(ci->PeerId()); + configPeerId = ci->PeerId(); + chatFlags = ci->chatFlags; + configFlags = confFlags; + sendTime = ci->sendTime; + message = ci->message; + recvTime = ci->recvTime; +} + +/* get data from RsPrivateChatMsgConfigItem to RsChatMsgItem */ +void RsPrivateChatMsgConfigItem::get(RsChatMsgItem *ci) +{ + ci->PeerId(configPeerId); + ci->chatFlags = chatFlags; + //configFlags not used + ci->sendTime = sendTime; + ci->message = message; + ci->recvTime = recvTime; +} + RsChatStatusItem::RsChatStatusItem(void *data,uint32_t size) : RsChatItem(RS_PKT_SUBTYPE_CHAT_STATUS) { diff --git a/libretroshare/src/serialiser/rsmsgitems.h b/libretroshare/src/serialiser/rsmsgitems.h index e6e0840b5..82f5c0e82 100644 --- a/libretroshare/src/serialiser/rsmsgitems.h +++ b/libretroshare/src/serialiser/rsmsgitems.h @@ -44,8 +44,11 @@ const uint32_t RS_CHAT_FLAG_PUBLIC = 0x0020; const uint32_t RS_CHAT_FLAG_REQUEST_CUSTOM_STATE = 0x0040; const uint32_t RS_CHAT_FLAG_CUSTOM_STATE_AVAILABLE = 0x0080; -const uint8_t RS_PKT_SUBTYPE_CHAT_AVATAR = 0x03 ; // default is 0x01 -const uint8_t RS_PKT_SUBTYPE_CHAT_STATUS = 0x04 ; // default is 0x01 +const uint32_t RS_CHATMSG_CONFIGFLAG_INCOMING = 0x0001; + +const uint8_t RS_PKT_SUBTYPE_CHAT_AVATAR = 0x03 ; // default is 0x01 +const uint8_t RS_PKT_SUBTYPE_CHAT_STATUS = 0x04 ; // default is 0x01 +const uint8_t RS_PKT_SUBTYPE_PRIVATECHATMSG_CONFIG = 0x05 ; // default is 0x01 // for defining tags themselves and msg tags const uint8_t RS_PKT_SUBTYPE_MSG_TAG_TYPE = 0x03; @@ -86,7 +89,37 @@ class RsChatMsgItem: public RsChatItem uint32_t sendTime; std::wstring message; /* not serialised */ - uint32_t recvTime; + uint32_t recvTime; +}; + +/*! + * For saving incoming and outgoing chat msgs + * @see p3ChatService + */ +class RsPrivateChatMsgConfigItem: public RsChatItem +{ + public: + RsPrivateChatMsgConfigItem() :RsChatItem(RS_PKT_SUBTYPE_PRIVATECHATMSG_CONFIG) {} + RsPrivateChatMsgConfigItem(void *data,uint32_t size) ; // deserialization + + virtual ~RsPrivateChatMsgConfigItem() {} + virtual void clear() {} + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + virtual bool serialise(void *data,uint32_t& size) ; // Isn't it better that items can serialize themselves ? + virtual uint32_t serial_size() ; // deserialise is handled using a constructor + + /* set data from RsChatMsgItem to RsPrivateChatMsgConfigItem */ + void set(RsChatMsgItem *ci, const std::string &peerId, uint32_t confFlags); + /* get data from RsPrivateChatMsgConfigItem to RsChatMsgItem */ + void get(RsChatMsgItem *ci); + + std::string configPeerId; + uint32_t chatFlags; + uint32_t configFlags; + uint32_t sendTime; + std::wstring message; + uint32_t recvTime; }; // This class contains activity info for the sending peer: active, idle, typing, etc. diff --git a/libretroshare/src/services/p3chatservice.cc b/libretroshare/src/services/p3chatservice.cc index 30929bcb6..ea37c61de 100644 --- a/libretroshare/src/services/p3chatservice.cc +++ b/libretroshare/src/services/p3chatservice.cc @@ -203,7 +203,7 @@ void p3ChatService::sendStatusString( const std::string& id , const std::string& sendItem(cs); } -int p3ChatService::sendPrivateChat(std::string &id, std::wstring &msg) +bool p3ChatService::sendPrivateChat(std::string &id, std::wstring &msg) { // make chat item.... #ifdef CHAT_DEBUG @@ -218,6 +218,20 @@ int p3ChatService::sendPrivateChat(std::string &id, std::wstring &msg) ci->sendTime = time(NULL); ci->message = msg; + if (!mConnMgr->isOnline(id)) { + /* peer is offline, add to outgoing list */ + { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + privateOutgoingList.push_back(ci); + } + + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_ADD); + + IndicateConfigChanged(); + + return false; + } + { RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ std::map::iterator it = _avatars.find(id) ; @@ -278,7 +292,7 @@ int p3ChatService::sendPrivateChat(std::string &id, std::wstring &msg) sendItem(cs) ; } - return 1; + return true; } void p3ChatService::receiveChatQueue() @@ -288,7 +302,7 @@ void p3ChatService::receiveChatQueue() time_t now = time(NULL); RsItem *item ; - + while(NULL != (item=recvItem())) { #ifdef CHAT_DEBUG @@ -348,7 +362,7 @@ void p3ChatService::receiveChatQueue() if (ci->chatFlags & RS_CHAT_FLAG_PRIVATE) { privateChanged = true; - privateList.push_back(ci); // don't delete the item !! + privateIncomingList.push_back(ci); // don't delete the item !! } else { publicChanged = true; publicList.push_back(ci); // don't delete the item !! @@ -413,18 +427,16 @@ void p3ChatService::receiveChatQueue() rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_PUBLIC_CHAT, NOTIFY_TYPE_ADD); } if (privateChanged) { - rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_PRIVATE_CHAT, NOTIFY_TYPE_ADD); + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_PRIVATE_INCOMING_CHAT, NOTIFY_TYPE_ADD); + + IndicateConfigChanged(); // only private chat messages are saved } } -int p3ChatService::getChatQueueCount(bool privateQueue) +int p3ChatService::getPublicChatQueueCount() { RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - if (privateQueue) { - return privateList.size(); - } - return publicList.size(); } @@ -462,19 +474,38 @@ bool p3ChatService::getPublicChatQueue(std::list &chats) return true; } -bool p3ChatService::getPrivateChatQueueIds(std::list &ids) +int p3ChatService::getPrivateChatQueueCount(bool incoming) +{ + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + if (incoming) { + return privateIncomingList.size(); + } + + return privateOutgoingList.size(); +} + +bool p3ChatService::getPrivateChatQueueIds(bool incoming, std::list &ids) { ids.clear(); RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + std::list *list; + + if (incoming) { + list = &privateIncomingList; + } else { + list = &privateOutgoingList; + } + // get the items from the private list. - if (privateList.size() == 0) { + if (list->size() == 0) { return false; } std::list::iterator it; - for (it = privateList.begin(); it != privateList.end(); it++) { + for (it = list->begin(); it != list->end(); it++) { RsChatMsgItem *c = *it; if (std::find(ids.begin(), ids.end(), c->PeerId()) == ids.end()) { @@ -485,34 +516,69 @@ bool p3ChatService::getPrivateChatQueueIds(std::list &ids) return true; } -bool p3ChatService::getPrivateChatQueue(std::string id, std::list &chats) +bool p3ChatService::getPrivateChatQueue(bool incoming, const std::string &id, std::list &chats) +{ + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + std::list *list; + + if (incoming) { + list = &privateIncomingList; + } else { + list = &privateOutgoingList; + } + + // get the items from the private list. + if (list->size() == 0) { + return false; + } + + std::list::iterator it; + for (it = list->begin(); it != list->end(); it++) { + RsChatMsgItem *c = *it; + + if (c->PeerId() == id) { + ChatInfo ci; + initRsChatInfo(c, ci); + chats.push_back(ci); + } + } + + return (chats.size() > 0); +} + +bool p3ChatService::clearPrivateChatQueue(bool incoming, const std::string &id) { bool changed = false; { RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + std::list *list; + + if (incoming) { + list = &privateIncomingList; + } else { + list = &privateOutgoingList; + } + // get the items from the private list. - if (privateList.size() == 0) { + if (list->size() == 0) { return false; } - std::list::iterator it = privateList.begin(); - while (it != privateList.end()) { + std::list::iterator it = list->begin(); + while (it != list->end()) { RsChatMsgItem *c = *it; if (c->PeerId() == id) { - ChatInfo ci; - initRsChatInfo(c, ci); - chats.push_back(ci); - - changed = true; - delete c; + changed = true; std::list::iterator it1 = it; it++; - privateList.erase(it1); + list->erase(it1); + continue; } @@ -521,7 +587,9 @@ bool p3ChatService::getPrivateChatQueue(std::string id, std::list &cha } /* UNLOCKED */ if (changed) { - rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_PRIVATE_CHAT, NOTIFY_TYPE_DEL); + rsicontrol->getNotify().notifyListChange(incoming ? NOTIFY_LIST_PRIVATE_INCOMING_CHAT : NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_DEL); + + IndicateConfigChanged(); } return true; @@ -833,6 +901,10 @@ bool p3ChatService::loadList(std::list load) RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ _own_avatar = new AvatarInfo(ai->image_data,ai->image_size) ; + + delete *it; + + continue; } RsChatStatusItem *mitem = NULL ; @@ -842,9 +914,38 @@ bool p3ChatService::loadList(std::list load) RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ _custom_status_string = mitem->status_string ; + + delete *it; + + continue; } + RsPrivateChatMsgConfigItem *citem = NULL ; + if(NULL != (citem = dynamic_cast(*it))) + { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + if (citem->chatFlags & RS_CHAT_FLAG_PRIVATE) { + RsChatMsgItem *ci = new RsChatMsgItem(); + citem->get(ci); + + if (citem->configFlags & RS_CHATMSG_CONFIGFLAG_INCOMING) { + privateIncomingList.push_back(ci); + } else { + privateOutgoingList.push_back(ci); + } + } else { + // ignore all other items + } + + + delete *it; + + continue; + } + + // delete unknown items delete *it; } return true; @@ -852,7 +953,10 @@ bool p3ChatService::loadList(std::list load) std::list p3ChatService::saveList(bool& cleanup) { - cleanup = true ; + cleanup = true; + + mChatMtx.lock(); /****** MUTEX LOCKED *******/ + /* now we create a pqistore, and stream all the msgs into it */ std::list list ; @@ -871,9 +975,36 @@ std::list p3ChatService::saveList(bool& cleanup) list.push_back(di) ; + /* save incoming private chat messages */ + + std::list::iterator it; + for (it = privateIncomingList.begin(); it != privateIncomingList.end(); it++) { + RsPrivateChatMsgConfigItem *ci = new RsPrivateChatMsgConfigItem; + + ci->set(*it, (*it)->PeerId(), RS_CHATMSG_CONFIGFLAG_INCOMING); + + list.push_back(ci); + } + + /* save outgoing private chat messages */ + + for (it = privateOutgoingList.begin(); it != privateOutgoingList.end(); it++) { + RsPrivateChatMsgConfigItem *ci = new RsPrivateChatMsgConfigItem; + + ci->set(*it, (*it)->PeerId(), 0); + + list.push_back(ci); + } + return list; } +void p3ChatService::saveDone() +{ + /* unlock mutex */ + mChatMtx.unlock(); /****** MUTEX UNLOCKED *******/ +} + RsSerialiser *p3ChatService::setupSerialiser() { RsSerialiser *rss = new RsSerialiser ; @@ -882,5 +1013,46 @@ RsSerialiser *p3ChatService::setupSerialiser() return rss ; } +/*************** pqiMonitor callback ***********************/ +void p3ChatService::statusChange(const std::list &plist) +{ + std::list::const_iterator it; + for (it = plist.begin(); it != plist.end(); it++) { + if (it->state & RS_PEER_S_FRIEND) { + if (it->actions & RS_PEER_CONNECTED) { + /* send the saved outgoing messages */ + bool changed = false; + if (privateOutgoingList.size()) { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + std::list::iterator cit = privateOutgoingList.begin(); + while (cit != privateOutgoingList.end()) { + RsChatMsgItem *c = *cit; + + if (c->PeerId() == it->id) { + sendItem(c); // delete item + + changed = true; + + std::list::iterator cit1 = cit; + cit++; + privateOutgoingList.erase(cit1); + + continue; + } + + cit++; + } + } /* UNLOCKED */ + + if (changed) { + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_DEL); + + IndicateConfigChanged(); + } + } + } + } +} diff --git a/libretroshare/src/services/p3chatservice.h b/libretroshare/src/services/p3chatservice.h index 99f011534..c32a906dd 100644 --- a/libretroshare/src/services/p3chatservice.h +++ b/libretroshare/src/services/p3chatservice.h @@ -42,12 +42,12 @@ * This service uses rsnotify (callbacks librs clients (e.g. rs-gui)) * @see NotifyBase */ -class p3ChatService: public p3Service, public p3Config +class p3ChatService: public p3Service, public p3Config, public pqiMonitor { public: p3ChatService(p3ConnectMgr *cm); - /* overloaded */ + /***** overloaded from p3Service *****/ /*! * This retrieves all chat msg items and also (important!) * processes chat-status items that are in service item queue. chat msg item requests are also processed and not returned @@ -58,16 +58,20 @@ class p3ChatService: public p3Service, public p3Config virtual int tick(); virtual int status(); + /*************** pqiMonitor callback ***********************/ + virtual void statusChange(const std::list &plist); + /*! * public chat sent to all peers */ int sendPublicChat(std::wstring &msg); + /********* RsMsgs ***********/ /*! * chat is sent to specifc peer * @param id peer to send chat msg to */ - int sendPrivateChat(std::string &id, std::wstring &msg); + bool sendPrivateChat(std::string &id, std::wstring &msg); /*! * can be used to send 'immediate' status msgs, these status updates are meant for immediate use by peer (not saved by rs) @@ -115,27 +119,37 @@ class p3ChatService: public p3Service, public p3Config */ void getOwnAvatarJpegData(unsigned char *& data,int& size) ; - /*! - * returns the count of messages in public or private queue + * returns the count of messages in public queue * @param public or private queue */ - int getChatQueueCount(bool privateQueue); + int getPublicChatQueueCount(); /*! * This retrieves all public chat msg items */ bool getPublicChatQueue(std::list &chats); + /*! + * returns the count of messages in private queue + * @param public or private queue + */ + int getPrivateChatQueueCount(bool incoming); + /*! * @param id's of available private chat messages */ - bool getPrivateChatQueueIds(std::list &ids); + bool getPrivateChatQueueIds(bool incoming, std::list &ids); /*! * This retrieves all private chat msg items for peer */ - bool getPrivateChatQueue(std::string id, std::list &chats); + bool getPrivateChatQueue(bool incoming, const std::string &id, std::list &chats); + + /*! + * @param clear private chat queue + */ + bool clearPrivateChatQueue(bool incoming, const std::string &id); /************* from p3Config *******************/ virtual RsSerialiser *setupSerialiser() ; @@ -144,6 +158,7 @@ class p3ChatService: public p3Service, public p3Config * chat msg items and custom status are saved */ virtual std::list saveList(bool& cleanup) ; + virtual void saveDone(); virtual bool loadList(std::list load) ; private: @@ -180,7 +195,8 @@ class p3ChatService: public p3Service, public p3Config p3ConnectMgr *mConnMgr; std::list publicList; - std::list privateList; + std::list privateIncomingList; + std::list privateOutgoingList; AvatarInfo *_own_avatar ; std::map _avatars ; diff --git a/retroshare-gui/src/gui/MainWindow.cpp b/retroshare-gui/src/gui/MainWindow.cpp index 06c300d92..148a9877e 100644 --- a/retroshare-gui/src/gui/MainWindow.cpp +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -308,6 +308,7 @@ MainWindow::MainWindow(QWidget* parent, Qt::WFlags flags) /* call once */ updateMessages(); updateForums(); + privateChatChanged(NOTIFY_LIST_PRIVATE_INCOMING_CHAT, NOTIFY_TYPE_ADD); idle = new Idle(); idle->start(); @@ -511,18 +512,20 @@ void MainWindow::updateStatus() } } -void MainWindow::privateChatChanged(int type) +void MainWindow::privateChatChanged(int list, int type) { /* first process the chat messages */ - PopupChatDialog::privateChatChanged(); + PopupChatDialog::privateChatChanged(list, type); - /* than count the chat messages */ - int chatCount = rsMsgs->getChatQueueCount(true); + if (list == NOTIFY_LIST_PRIVATE_INCOMING_CHAT) { + /* than count the chat messages */ + int chatCount = rsMsgs->getPrivateChatQueueCount(true); - if (chatCount) { - trayIconChat->show(); - } else { - trayIconChat->hide(); + if (chatCount) { + trayIconChat->show(); + } else { + trayIconChat->hide(); + } } } @@ -833,7 +836,7 @@ void MainWindow::trayIconChatClicked(QSystemTrayIcon::ActivationReason e) if(e == QSystemTrayIcon::Trigger || e == QSystemTrayIcon::DoubleClick) { PopupChatDialog *pcd = NULL; std::list ids; - if (rsMsgs->getPrivateChatQueueIds(ids) && ids.size()) { + if (rsMsgs->getPrivateChatQueueIds(true, ids) && ids.size()) { pcd = PopupChatDialog::getPrivateChat(ids.front(), RS_CHAT_OPEN_NEW | RS_CHAT_REOPEN | RS_CHAT_FOCUS); } diff --git a/retroshare-gui/src/gui/MainWindow.h b/retroshare-gui/src/gui/MainWindow.h index ffa691af2..cac7d0ab3 100644 --- a/retroshare-gui/src/gui/MainWindow.h +++ b/retroshare-gui/src/gui/MainWindow.h @@ -141,7 +141,7 @@ public slots: void checkAndSetIdle(int idleTime); void updateMessages(); void updateForums(); - void privateChatChanged(int type); + void privateChatChanged(int list, int type); protected: /** Default Constructor */ diff --git a/retroshare-gui/src/gui/MessengerWindow.cpp b/retroshare-gui/src/gui/MessengerWindow.cpp index 5e2f6245b..86abb520c 100644 --- a/retroshare-gui/src/gui/MessengerWindow.cpp +++ b/retroshare-gui/src/gui/MessengerWindow.cpp @@ -439,7 +439,7 @@ void MessengerWindow::insertPeers() std::list privateChatIds; #ifndef MINIMAL_RSGUI - rsMsgs->getPrivateChatQueueIds(privateChatIds); + rsMsgs->getPrivateChatQueueIds(true, privateChatIds); #endif // MINIMAL_RSGUI rsPeers->getGPGAcceptedList(gpgFriends); diff --git a/retroshare-gui/src/gui/PeersDialog.cpp b/retroshare-gui/src/gui/PeersDialog.cpp index 3d86b5554..7bc6d573e 100644 --- a/retroshare-gui/src/gui/PeersDialog.cpp +++ b/retroshare-gui/src/gui/PeersDialog.cpp @@ -474,7 +474,7 @@ void PeersDialog::insertPeers() bool bHideUnconnected = ui.action_Hide_Offline_Friends->isChecked(); std::list privateChatIds; - rsMsgs->getPrivateChatQueueIds(privateChatIds); + rsMsgs->getPrivateChatQueueIds(true, privateChatIds); rsPeers->getGPGAcceptedList(gpgFriends); diff --git a/retroshare-gui/src/gui/chat/PopupChatDialog.cpp b/retroshare-gui/src/gui/chat/PopupChatDialog.cpp index 08f6f2958..a33cc17ed 100644 --- a/retroshare-gui/src/gui/chat/PopupChatDialog.cpp +++ b/retroshare-gui/src/gui/chat/PopupChatDialog.cpp @@ -127,8 +127,10 @@ PopupChatDialog::PopupChatDialog(std::string id, std::string name, connect(ui.colorButton, SIGNAL(clicked()), this, SLOT(setColor())); connect(ui.emoteiconButton, SIGNAL(clicked()), this, SLOT(smileyWidget())); connect(ui.actionSave_Chat_History, SIGNAL(triggered()), this, SLOT(fileSaveAs())); + connect(ui.actionClearOfflineMessages, SIGNAL(triggered()), this, SLOT(clearOfflineMessages())); connect(ui.textBrowser, SIGNAL(anchorClicked(const QUrl &)), SLOT(anchorClicked(const QUrl &))); + connect(ui.offlineTextBrowser, SIGNAL(anchorClicked(const QUrl &)), SLOT(anchorClicked(const QUrl &))); connect(NotifyQt::getInstance(), SIGNAL(peerStatusChanged(const QString&, int)), this, SLOT(updateStatus(const QString&, int))); connect(NotifyQt::getInstance(), SIGNAL(peerHasNewCustomStateString(const QString&, const QString&)), this, SLOT(updatePeersCustomStateString(const QString&, const QString&))); @@ -164,6 +166,7 @@ PopupChatDialog::PopupChatDialog(std::string id, std::string name, QMenu * toolmenu = new QMenu(); toolmenu->addAction(ui.actionClear_Chat); toolmenu->addAction(ui.actionSave_Chat_History); + toolmenu->addAction(ui.actionClearOfflineMessages); //toolmenu->addAction(ui.action_Disable_Emoticons); ui.pushtoolsButton->setMenu(toolmenu); @@ -198,6 +201,9 @@ PopupChatDialog::PopupChatDialog(std::string id, std::string name, updatePeersCustomStateString(QString::fromStdString(dialogId), customStateString); ui.chattextEdit->installEventFilter(this); + + // call once + onPrivateChatChanged(NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_ADD); } /** Destructor. */ @@ -321,24 +327,29 @@ void PopupChatDialog::processSettings(bool bLoad) chatDialogs.clear(); } -/*static*/ void PopupChatDialog::privateChatChanged() +/*static*/ void PopupChatDialog::privateChatChanged(int list, int type) { - std::list ids; - if (!rsMsgs->getPrivateChatQueueIds(ids)) { -#ifdef PEERS_DEBUG - std::cerr << "no chat available." << std::endl ; -#endif - return; + if (list == NOTIFY_LIST_PRIVATE_INCOMING_CHAT && type == NOTIFY_TYPE_ADD) { + std::list ids; + if (rsMsgs->getPrivateChatQueueIds(true, ids)) { + uint chatflags = Settings->getChatFlags(); + + std::list::iterator id; + for (id = ids.begin(); id != ids.end(); id++) { + PopupChatDialog *pcd = getPrivateChat(*id, chatflags); + + if (pcd) { + pcd->insertChatMsgs(); + } + } + } } - uint chatflags = Settings->getChatFlags(); - - std::list::iterator id; - for (id = ids.begin(); id != ids.end(); id++) { - PopupChatDialog *pcd = getPrivateChat(*id, chatflags); - - if (pcd) { - pcd->insertChatMsgs(); + /* now notify all open priavate chat windows */ + std::map::iterator it; + for (it = chatDialogs.begin (); it != chatDialogs.end(); it++) { + if (it->second) { + it->second->onPrivateChatChanged(list, type); } } } @@ -349,37 +360,45 @@ void PopupChatDialog::chatFriend(std::string id) return; } std::cerr<<" popup dialog chat friend 1"<getPeerDetails(id, detail)) { return; } - + + std::string firstId; + if (detail.isOnlyGPGdetail) { //let's get the ssl child details, and open all the chat boxes std::list sslIds; rsPeers->getSSLChildListOfGPGId(detail.gpg_id, sslIds); for (std::list::iterator it = sslIds.begin(); it != sslIds.end(); it++) { + if (firstId.empty()) { + firstId = *it; + } + RsPeerDetails sslDetails; if (rsPeers->getPeerDetails(*it, sslDetails)) { if (sslDetails.state & RS_PEER_STATE_CONNECTED) { - oneLocationConnected = true; getPrivateChat(*it, RS_CHAT_OPEN_NEW | RS_CHAT_REOPEN | RS_CHAT_FOCUS); + return; } } } } else { if (detail.state & RS_PEER_STATE_CONNECTED) { - oneLocationConnected = true; getPrivateChat(id, RS_CHAT_OPEN_NEW | RS_CHAT_REOPEN | RS_CHAT_FOCUS); + return; } + firstId = id; } - if (!oneLocationConnected) { - /* info dialog */ - if ((QMessageBox::question(NULL, tr("Friend not Online"),tr("Your Friend is offline \nDo you want to send them a Message instead"),QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes))== QMessageBox::Yes) { - MessageComposer::msgFriend(id); + /* info dialog */ + if ((QMessageBox::question(NULL, tr("Friend not Online"),tr("Your Friend is offline \nDo you want to send them a Message instead"),QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes))== QMessageBox::Yes) { + MessageComposer::msgFriend(id); + } else { + if (firstId.empty() == false) { + getPrivateChat(firstId, RS_CHAT_OPEN_NEW | RS_CHAT_REOPEN | RS_CHAT_FOCUS); } } } @@ -505,6 +524,32 @@ void PopupChatDialog::updateChat() } +void PopupChatDialog::onPrivateChatChanged(int list, int type) +{ + if (list == NOTIFY_LIST_PRIVATE_OUTGOING_CHAT && type) { + std::list offlineChat; + if (rsMsgs->getPrivateChatQueueCount(false) && rsMsgs->getPrivateChatQueue(false, dialogId, offlineChat)) { + ui.actionClearOfflineMessages->setEnabled(true); + ui.offlineTextBrowser->setVisible(true); + + std::list::iterator it; + for(it = offlineChat.begin(); it != offlineChat.end(); it++) { + /* are they public? */ + if ((it->chatflags & RS_CHAT_PRIVATE) == 0) { + /* this should not happen */ + continue; + } + + addChatMsg(it->rsid, it->sendTime, it->msg, true); + } + } else { + ui.actionClearOfflineMessages->setEnabled(false); + ui.offlineTextBrowser->setVisible(false); + ui.offlineTextBrowser->clear(); + } + } +} + void PopupChatDialog::insertChatMsgs() { if (isVisible() == false) { @@ -515,7 +560,7 @@ void PopupChatDialog::insertChatMsgs() m_bInsertOnVisible = false; std::list newchat; - if (!rsMsgs->getPrivateChatQueue(dialogId, newchat)) + if (!rsMsgs->getPrivateChatQueue(true, dialogId, newchat)) { #ifdef PEERS_DEBUG std::cerr << "no chat for " << dialogId << " available." << std::endl ; @@ -531,17 +576,21 @@ void PopupChatDialog::insertChatMsgs() continue; } - addChatMsg(it->rsid, it->sendTime, it->msg); + addChatMsg(it->rsid, it->sendTime, it->msg, false); } + rsMsgs->clearPrivateChatQueue(true, dialogId); + playsound(); QApplication::alert(this); } -void PopupChatDialog::addChatMsg(std::string &id, uint sendTime, std::wstring &msg) +void PopupChatDialog::addChatMsg(std::string &id, uint sendTime, std::wstring &msg, bool offline) { + std::string ownId = rsPeers->getOwnId(); + QDateTime timestamp = QDateTime::fromTime_t(sendTime); - QString name = QString::fromStdString(rsPeers->getPeerName(id)); + QString name = QString::fromStdString(rsPeers->getPeerName(offline ? ownId : id)); QString message = QString::fromStdWString(msg); #ifdef CHAT_DEBUG @@ -555,10 +604,14 @@ void PopupChatDialog::addChatMsg(std::string &id, uint sendTime, std::wstring &m formatFlag |= CHAT_FORMATMSG_EMBED_SMILEYS; } - ChatStyle::enumFormatMessage type = (id == rsPeers->getOwnId()) ? ChatStyle::FORMATMSG_INCOMING : ChatStyle::FORMATMSG_OUTGOING; + ChatStyle::enumFormatMessage type = (offline == false && id == ownId) ? ChatStyle::FORMATMSG_INCOMING : ChatStyle::FORMATMSG_OUTGOING; QString formatMsg = style.formatMessage(type, name, timestamp, message, formatFlag); + if (offline) { + ui.offlineTextBrowser->append(formatMsg); + } + ui.textBrowser->append(formatMsg); resetStatusBar() ; @@ -627,9 +680,10 @@ void PopupChatDialog::sendChat() std::cout << "PopupChatDialog:sendChat " << std::endl; #endif - addChatMsg(ownId, time(NULL), msg); + if (rsMsgs->sendPrivateChat(dialogId, msg)) { + addChatMsg(ownId, time(NULL), msg, false); + } - rsMsgs->sendPrivateChat(dialogId, msg); chatWidget->clear(); setFont(); @@ -928,9 +982,9 @@ void PopupChatDialog::fileHashingFinished(AttachFileItem* file) std::wstring msg = message.toStdWString(); - addChatMsg(ownId, time(NULL), msg); - - rsMsgs->sendPrivateChat(dialogId, msg); + if (rsMsgs->sendPrivateChat(dialogId, msg)) { + addChatMsg(ownId, time(NULL), msg, false); + } } void PopupChatDialog::anchorClicked (const QUrl& link ) @@ -1062,6 +1116,11 @@ void PopupChatDialog::setCurrentFileName(const QString &fileName) setWindowModified(false); } +void PopupChatDialog::clearOfflineMessages() +{ + rsMsgs->clearPrivateChatQueue(false, dialogId); +} + void PopupChatDialog::updateStatus(const QString &peer_id, int status) { std::string stdPeerId = peer_id.toStdString(); diff --git a/retroshare-gui/src/gui/chat/PopupChatDialog.h b/retroshare-gui/src/gui/chat/PopupChatDialog.h index b2fa7c992..4c87d07fa 100644 --- a/retroshare-gui/src/gui/chat/PopupChatDialog.h +++ b/retroshare-gui/src/gui/chat/PopupChatDialog.h @@ -42,7 +42,7 @@ public: static void cleanupChat(); static void chatFriend(std::string id); static void updateAllAvatars(); - static void privateChatChanged(); + static void privateChatChanged(int list, int type); void updateChat(); void updatePeerAvatar(const std::string&); @@ -83,7 +83,7 @@ protected: bool eventFilter(QObject *obj, QEvent *ev); void insertChatMsgs(); - void addChatMsg(std::string &id, uint sendTime, std::wstring &msg); + void addChatMsg(std::string &id, uint sendTime, std::wstring &msg, bool offline); void updateAvatar(); @@ -108,16 +108,20 @@ private slots: bool fileSave(); bool fileSaveAs(); - void setCurrentFileName(const QString &fileName); + void clearOfflineMessages(); private: + void setCurrentFileName(const QString &fileName); + void colorChanged(const QColor &c); void fontChanged(const QFont &font); void addAttachment(std::string,int flag); void processSettings(bool bLoad); + void onPrivateChatChanged(int list, int type); + QAction *actionTextBold; QAction *actionTextUnderline; QAction *actionTextItalic; diff --git a/retroshare-gui/src/gui/chat/PopupChatDialog.ui b/retroshare-gui/src/gui/chat/PopupChatDialog.ui index b97ae5421..aa3938327 100644 --- a/retroshare-gui/src/gui/chat/PopupChatDialog.ui +++ b/retroshare-gui/src/gui/chat/PopupChatDialog.ui @@ -38,7 +38,7 @@ stop:0 #F6FCFF, stop:1 #F6FCFF);} 1 - + @@ -109,7 +109,7 @@ stop:0 #F6FCFF, stop:1 #F6FCFF);} - + @@ -355,121 +355,7 @@ border-image: url(:/images/closepressed.png) - - - - 1 - - - Qt::Vertical - - - 2 - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 0 - 0 - - - - QTextBrowser{border: 1px solid #B8B6B1; -border-radius: 6px; -background: white;} - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> - - - true - - - false - - - - - - 0 - - - - - - - - 0 - - - 3 - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - QTextEdit{border: 1px solid #B8B6B1; -border-radius: 6px; -background: white;} - - - - - - - - 18 - 18 - - - - - 18 - 18 - - - - T - - - Qt::AlignCenter - - - - - - - - + @@ -823,9 +709,150 @@ border: 1px solid #CCCCCC; - + + + + + 1 + + + Qt::Vertical + + + 2 + + + + + + + + 0 + 0 + + + + + 0 + 100 + + + + QTextBrowser{border: 1px solid #B8B6B1; +border-radius: 6px; +background: white;} + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + true + + + false + + + + + + + + 0 + 0 + + + + + 0 + 100 + + + + QTextBrowser{border: 1px solid #B8B6B1; +border-radius: 6px; +background: white;} + + + true + + + false + + + + + + + + + 0 + + + + + + + + 0 + + + 3 + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + QTextEdit{border: 1px solid #B8B6B1; +border-radius: 6px; +background: white;} + + + + + + + + 18 + 18 + + + + + 18 + 18 + + + + T + + + Qt::AlignCenter + + + + + + + @@ -916,6 +943,11 @@ border: 1px solid #CCCCCC; Save Chat History + + + Clear offline messages + + diff --git a/retroshare-gui/src/gui/notifyqt.cpp b/retroshare-gui/src/gui/notifyqt.cpp index 8d9681d63..b9c129938 100644 --- a/retroshare-gui/src/gui/notifyqt.cpp +++ b/retroshare-gui/src/gui/notifyqt.cpp @@ -232,11 +232,12 @@ void NotifyQt::notifyListChange(int list, int type) #endif emit publicChatChanged(type); break; - case NOTIFY_LIST_PRIVATE_CHAT: + case NOTIFY_LIST_PRIVATE_INCOMING_CHAT: + case NOTIFY_LIST_PRIVATE_OUTGOING_CHAT: #ifdef NOTIFY_DEBUG std::cerr << "received private chat changed" << std::endl ; #endif - emit privateChatChanged(type); + emit privateChatChanged(list, type); break; default: break; diff --git a/retroshare-gui/src/gui/notifyqt.h b/retroshare-gui/src/gui/notifyqt.h index 975e1a735..7234a63ca 100644 --- a/retroshare-gui/src/gui/notifyqt.h +++ b/retroshare-gui/src/gui/notifyqt.h @@ -76,7 +76,7 @@ class NotifyQt: public QObject, public NotifyBase void peerStatusChanged(const QString& /* peer_id */, int /* status */); void peerStatusChangedSummary() const; void publicChatChanged(int type) const ; - void privateChatChanged(int type) const ; + void privateChatChanged(int list, int type) const ; /* Notify from GUI */ void chatStyleChanged(int /*ChatStyle::enumStyleType*/ styleType); diff --git a/retroshare-gui/src/main.cpp b/retroshare-gui/src/main.cpp index 060c2ee57..a342a6624 100644 --- a/retroshare-gui/src/main.cpp +++ b/retroshare-gui/src/main.cpp @@ -189,7 +189,7 @@ int main(int argc, char *argv[]) QObject::connect(notify,SIGNAL(transfersChanged()) ,w->transfersDialog ,SLOT(insertTransfers() )) ; QObject::connect(notify,SIGNAL(friendsChanged()) ,w->peersDialog ,SLOT(insertPeers() )) ; QObject::connect(notify,SIGNAL(publicChatChanged(int)) ,w->peersDialog ,SLOT(publicChatChanged(int) )); - QObject::connect(notify,SIGNAL(privateChatChanged(int)) ,w ,SLOT(privateChatChanged(int) )); + QObject::connect(notify,SIGNAL(privateChatChanged(int, int)) ,w ,SLOT(privateChatChanged(int, int) )); QObject::connect(notify,SIGNAL(neighborsChanged()) ,w->networkDialog ,SLOT(insertConnect() )) ; QObject::connect(notify,SIGNAL(messagesChanged()) ,w->messagesDialog ,SLOT(insertMessages() )) ; QObject::connect(notify,SIGNAL(messagesTagsChanged()) ,w->messagesDialog ,SLOT(messagesTagsChanged() )) ;