diff --git a/libretroshare/src/rsiface/rsiface.h b/libretroshare/src/rsiface/rsiface.h index 6d7bc69f9..1dc8326bb 100644 --- a/libretroshare/src/rsiface/rsiface.h +++ b/libretroshare/src/rsiface/rsiface.h @@ -200,6 +200,7 @@ class NotifyBase virtual void notifyListChange(int list, int type) { (void) list; (void) type; return; } virtual void notifyErrorMsg(int list, int sev, std::string msg) { (void) list; (void) sev; (void) msg; return; } virtual void notifyChat() { return; } + virtual void notifyChatStatus(const std::string& peer_id,const std::string& status_string) {} virtual void notifyHashingInfo(std::string fileinfo) { (void)fileinfo; return ; } virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list& files) { (void)files; } }; diff --git a/libretroshare/src/rsiface/rsmsgs.h b/libretroshare/src/rsiface/rsmsgs.h index bc6c2e2d6..f83a7b647 100644 --- a/libretroshare/src/rsiface/rsmsgs.h +++ b/libretroshare/src/rsiface/rsmsgs.h @@ -131,6 +131,7 @@ virtual bool MessageRead(std::string mid) = 0; virtual bool chatAvailable() = 0; virtual bool ChatSend(ChatInfo &ci) = 0; virtual bool getNewChat(std::list &chats) = 0; +virtual void sendStatusString(const std::string& id,const std::string& status_string) = 0 ; // get avatar data for peer pid virtual void getAvatarData(std::string pid,unsigned char *& data,int& size) = 0 ; diff --git a/libretroshare/src/rsserver/p3msgs.cc b/libretroshare/src/rsserver/p3msgs.cc index e420aa60f..a3bead43b 100644 --- a/libretroshare/src/rsserver/p3msgs.cc +++ b/libretroshare/src/rsserver/p3msgs.cc @@ -109,6 +109,11 @@ bool p3Msgs::ChatSend(ChatInfo &ci) return true; } +void p3Msgs::sendStatusString(const std::string& peer_id,const std::string& status_string) +{ + mChatSrv->sendStatusString(peer_id,status_string); +} + bool p3Msgs::chatAvailable() { return mChatSrv->receivedItems(); @@ -119,13 +124,13 @@ bool p3Msgs::getNewChat(std::list &chats) /* get any messages and push them to iface */ // get the items from the list. - std::list clist = mChatSrv -> getChatQueue(); + std::list clist = mChatSrv -> getChatQueue(); if (clist.size() < 1) { return false; } - std::list::iterator it; + std::list::iterator it; for(it = clist.begin(); it != clist.end(); it++) { ChatInfo ci; @@ -142,7 +147,7 @@ bool p3Msgs::getNewChat(std::list &chats) * for intAddChannel / intAddChannelMsg. */ -void p3Msgs::initRsChatInfo(RsChatItem *c, ChatInfo &i) +void p3Msgs::initRsChatInfo(RsChatMsgItem *c, ChatInfo &i) { i.rsid = c -> PeerId(); i.name = mAuthMgr->getName(i.rsid); diff --git a/libretroshare/src/rsserver/p3msgs.h b/libretroshare/src/rsserver/p3msgs.h index c3ee6c590..b1a5bfefa 100644 --- a/libretroshare/src/rsserver/p3msgs.h +++ b/libretroshare/src/rsserver/p3msgs.h @@ -32,7 +32,7 @@ class p3AuthMgr; class p3MsgService; class p3ChatService; -class RsChatItem; +class RsChatMsgItem; class p3Msgs: public RsMsgs { @@ -62,13 +62,14 @@ class p3Msgs: public RsMsgs virtual bool chatAvailable(); virtual bool ChatSend(ChatInfo &ci); virtual bool getNewChat(std::list &chats); + virtual void sendStatusString(const std::string& peer_id,const std::string& status_string) ; /****************************************/ private: - void initRsChatInfo(RsChatItem *c, ChatInfo &i); + void initRsChatInfo(RsChatMsgItem *c, ChatInfo &i); p3AuthMgr *mAuthMgr; p3MsgService *mMsgSrv; diff --git a/libretroshare/src/serialiser/rsmsgitems.cc b/libretroshare/src/serialiser/rsmsgitems.cc index 9e77244dc..69ba5f2f2 100644 --- a/libretroshare/src/serialiser/rsmsgitems.cc +++ b/libretroshare/src/serialiser/rsmsgitems.cc @@ -24,6 +24,7 @@ * */ +#include #include "serialiser/rsbaseserial.h" #include "serialiser/rsmsgitems.h" #include "serialiser/rstlvbase.h" @@ -36,64 +37,118 @@ /*************************************************************************/ -RsChatItem::~RsChatItem() +std::ostream& RsChatMsgItem::print(std::ostream &out, uint16_t indent) { - return; -} - -void RsChatItem::clear() -{ - chatFlags = 0; - sendTime = 0; - message.clear(); -} - -std::ostream &RsChatItem::print(std::ostream &out, uint16_t indent) -{ - printRsItemBase(out, "RsChatItem", indent); + printRsItemBase(out, "RsChatMsgItem", indent); uint16_t int_Indent = indent + 2; - printIndent(out, int_Indent); - out << "QblogMs " << chatFlags << std::endl; + printIndent(out, int_Indent); + out << "QblogMs " << chatFlags << std::endl; - printIndent(out, int_Indent); - out << "sendTime: " << sendTime << std::endl; + printIndent(out, int_Indent); + out << "sendTime: " << sendTime << std::endl; - printIndent(out, int_Indent); + printIndent(out, int_Indent); std::string cnv_message(message.begin(), message.end()); - out << "msg: " << cnv_message << std::endl; + out << "msg: " << cnv_message << std::endl; - printRsItemEnd(out, "RsChatItem", indent); - return out; + printRsItemEnd(out, "RsChatMsgItem", indent); + return out; } +std::ostream& RsChatStatusItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsChatStatusItem", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "Status string: " << status_string << std::endl; -uint32_t RsChatSerialiser::sizeItem(RsChatItem *item) + printRsItemEnd(out, "RsChatStatusItem", indent); + return out; +} + +RsItem *RsChatSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + +#ifdef CHAT_DEBUG + std::cerr << "deserializing packet..."<< std::endl ; +#endif + // look what we have... + if (*pktsize < rssize) /* check size */ + { +#ifdef CHAT_DEBUG + std::cerr << "chat deserialisation: not enough size: pktsize=" << *pktsize << ", rssize=" << rssize << std::endl ; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *pktsize = rssize; + + /* ready to load */ + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_TYPE_CHAT != getRsItemService(rstype))) + { +#ifdef CHAT_DEBUG + std::cerr << "chat deserialisation: wrong type !" << std::endl ; +#endif + return NULL; /* wrong type */ + } + + try + { + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_DEFAULT: return new RsChatMsgItem(data,*pktsize) ; + case RS_PKT_SUBTYPE_CHAT_STATUS: return new RsChatStatusItem(data,*pktsize) ; + default: + std::cerr << "Unknown packet type in chat!" << std::endl ; + return NULL ; + } + } + catch(std::exception& e) + { + std::cerr << "Exception raised: " << e.what() << std::endl ; + return NULL ; + } +} + +uint32_t RsChatMsgItem::serial_size() { uint32_t s = 8; /* header */ s += 4; /* chatFlags */ s += 4; /* sendTime */ - s += GetTlvWideStringSize(item->message); + s += GetTlvWideStringSize(message); + + return s; +} + +uint32_t RsChatStatusItem::serial_size() +{ + uint32_t s = 8; /* header */ + s += GetTlvStringSize(status_string); /* status */ return s; } /* serialise the data to the buffer */ -bool RsChatSerialiser::serialiseItem(RsChatItem *item, void *data, uint32_t *pktsize) +bool RsChatMsgItem::serialise(void *data, uint32_t& pktsize) { - uint32_t tlvsize = sizeItem(item); + uint32_t tlvsize = serial_size() ; uint32_t offset = 0; - if (*pktsize < tlvsize) + if (pktsize < tlvsize) return false; /* not enough space */ - *pktsize = tlvsize; + pktsize = tlvsize; bool ok = true; - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + ok &= setRsItemHeader(data, tlvsize, PacketId(), tlvsize); -#ifdef RSSERIAL_DEBUG +#ifdef CHAT_DEBUG std::cerr << "RsChatSerialiser::serialiseItem() Header: " << ok << std::endl; std::cerr << "RsChatSerialiser::serialiseItem() Size: " << tlvsize << std::endl; #endif @@ -102,94 +157,104 @@ bool RsChatSerialiser::serialiseItem(RsChatItem *item, void *data, uint32_t offset += 8; /* add mandatory parts first */ - ok &= setRawUInt32(data, tlvsize, &offset, item->chatFlags); - ok &= setRawUInt32(data, tlvsize, &offset, item->sendTime); - ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_MSG, item->message); + ok &= setRawUInt32(data, tlvsize, &offset, chatFlags); + ok &= setRawUInt32(data, tlvsize, &offset, sendTime); + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_MSG, message); if (offset != tlvsize) { ok = false; -#ifdef RSSERIAL_DEBUG +#ifdef CHAT_DEBUG std::cerr << "RsChatSerialiser::serialiseItem() Size Error! " << std::endl; #endif } -#ifdef RSSERIAL_DEBUG +#ifdef CHAT_DEBUG std::cerr << "computed size: " << 256*((unsigned char*)data)[6]+((unsigned char*)data)[7] << std::endl ; #endif return ok; } -RsChatItem *RsChatSerialiser::deserialiseItem(void *data, uint32_t *pktsize) +bool RsChatStatusItem::serialise(void *data, uint32_t& pktsize) { - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - + uint32_t tlvsize = serial_size() ; uint32_t offset = 0; + if (pktsize < tlvsize) + return false; /* not enough space */ - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_CHAT != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_DEFAULT != getRsItemSubType(rstype))) - { - return NULL; /* wrong type */ - } - - if (*pktsize < rssize) /* check size */ - return NULL; /* not enough data */ - - /* set the packet length */ - *pktsize = rssize; + pktsize = tlvsize; bool ok = true; - /* ready to load */ - RsChatItem *item = new RsChatItem(); - item->clear(); + ok &= setRsItemHeader(data, tlvsize, PacketId(), tlvsize); + +#ifdef CHAT_DEBUG + std::cerr << "RsChatSerialiser serialising chat status item." << std::endl; + 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_MSG, status_string); + + if (offset != tlvsize) + { + ok = false; +#ifdef CHAT_DEBUG + std::cerr << "RsChatSerialiser::serialiseItem() Size Error! " << std::endl; +#endif + } +#ifdef CHAT_DEBUG + std::cerr << "computed size: " << 256*((unsigned char*)data)[6]+((unsigned char*)data)[7] << std::endl ; +#endif + + return ok; +} + +RsChatMsgItem::RsChatMsgItem(void *data,uint32_t size) + : RsChatItem(RS_PKT_SUBTYPE_DEFAULT) +{ + uint32_t offset = 8; // skip the header + uint32_t rssize = getRsItemSize(data); + bool ok = true ; + /* get mandatory parts first */ - ok &= getRawUInt32(data, rssize, &offset, &(item->chatFlags)); - ok &= getRawUInt32(data, rssize, &offset, &(item->sendTime)); - ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_MSG, item->message); + ok &= getRawUInt32(data, rssize, &offset, &chatFlags); + ok &= getRawUInt32(data, rssize, &offset, &sendTime); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_MSG, message); + +#ifdef CHAT_DEBUG + std::cerr << "Building new chat msg item." << std::endl ; +#endif + if (offset != rssize) + throw std::runtime_error("Size error while deserializing.") ; + if (!ok) + throw std::runtime_error("Unknown error while deserializing.") ; +} + +RsChatStatusItem::RsChatStatusItem(void *data,uint32_t size) + : RsChatItem(RS_PKT_SUBTYPE_CHAT_STATUS) +{ + uint32_t offset = 8; // skip the header + uint32_t rssize = getRsItemSize(data); + bool ok = true ; + +#ifdef CHAT_DEBUG + std::cerr << "Building new chat status item." << std::endl ; +#endif + /* get mandatory parts first */ + ok &= GetTlvString(data, rssize, &offset,TLV_TYPE_STR_MSG, status_string); if (offset != rssize) - { - /* error */ - delete item; - return NULL; - } - + throw std::runtime_error("Size error while deserializing.") ; if (!ok) - { - delete item; - return NULL; - } - - return item; + throw std::runtime_error("Unknown error while deserializing.") ; } - -uint32_t RsChatSerialiser::size(RsItem *item) -{ - return sizeItem((RsChatItem *) item); -} - -bool RsChatSerialiser::serialise(RsItem *item, void *data, uint32_t *pktsize) -{ - return serialiseItem((RsChatItem *) item, data, pktsize); -} - -RsItem *RsChatSerialiser::deserialise(void *data, uint32_t *pktsize) -{ - return deserialiseItem(data, pktsize); -} - - - /*************************************************************************/ diff --git a/libretroshare/src/serialiser/rsmsgitems.h b/libretroshare/src/serialiser/rsmsgitems.h index d319e3288..ac51f77f3 100644 --- a/libretroshare/src/serialiser/rsmsgitems.h +++ b/libretroshare/src/serialiser/rsmsgitems.h @@ -35,51 +35,78 @@ /**************************************************************************/ /* chat Flags */ -const uint32_t RS_CHAT_FLAG_PRIVATE = 0x0001; -const uint32_t RS_CHAT_FLAG_REQUESTS_AVATAR = 0x0002; -const uint32_t RS_CHAT_FLAG_CONTAINS_AVATAR = 0x0004; +const uint32_t RS_CHAT_FLAG_PRIVATE = 0x0001; +const uint32_t RS_CHAT_FLAG_REQUESTS_AVATAR = 0x0002; +const uint32_t RS_CHAT_FLAG_CONTAINS_AVATAR = 0x0004; const uint32_t RS_CHAT_FLAG_AVATAR_AVAILABLE = 0x0008; +const uint8_t RS_PKT_SUBTYPE_CHAT_STATUS = 0x02 ; // default is 0x01 + class RsChatItem: public RsItem { public: - RsChatItem() - :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_CHAT, - RS_PKT_SUBTYPE_DEFAULT) - { return; } -virtual ~RsChatItem(); -virtual void clear(); -std::ostream &print(std::ostream &out, uint16_t indent = 0); + RsChatItem(uint8_t chat_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_CHAT,chat_subtype) {} - uint32_t chatFlags; - uint32_t sendTime; + virtual ~RsChatItem() {} + virtual void clear() {} + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) = 0 ; - std::wstring message; + virtual bool serialise(void *data,uint32_t& size) = 0 ; // Isn't it better that items can serialize themselves ? + virtual uint32_t serial_size() = 0 ; // deserialise is handled using a constructor +}; - /* not serialised */ - uint32_t recvTime; + +class RsChatMsgItem: public RsChatItem +{ + public: + RsChatMsgItem() :RsChatItem(RS_PKT_SUBTYPE_DEFAULT) {} + RsChatMsgItem(void *data,uint32_t size) ; // deserialization + + virtual ~RsChatMsgItem() {} + 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 + + uint32_t chatFlags; + uint32_t sendTime; + std::wstring message; + /* not serialised */ + uint32_t recvTime; +}; + +// This class contains activity info for the sending peer: active, idle, typing, etc. +// +class RsChatStatusItem: public RsChatItem +{ + public: + RsChatStatusItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_STATUS) {} + RsChatStatusItem(void *data,uint32_t size) ; // deserialization + + virtual ~RsChatStatusItem() {} + 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 + + std::string status_string; }; class RsChatSerialiser: public RsSerialType { public: - RsChatSerialiser() - :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_CHAT) - { return; } -virtual ~RsChatSerialiser() - { return; } - -virtual uint32_t size(RsItem *); -virtual bool serialise (RsItem *item, void *data, uint32_t *size); -virtual RsItem * deserialise(void *data, uint32_t *size); - - private: - -virtual uint32_t sizeItem(RsChatItem *); -virtual bool serialiseItem (RsChatItem *item, void *data, uint32_t *size); -virtual RsChatItem *deserialiseItem(void *data, uint32_t *size); - + RsChatSerialiser() :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_CHAT) {} + virtual uint32_t size (RsItem *item) + { + return static_cast(item)->serial_size() ; + } + virtual bool serialise(RsItem *item, void *data, uint32_t *size) + { + return static_cast(item)->serialise(data,*size) ; + } + virtual RsItem *deserialise (void *data, uint32_t *size) ; }; /**************************************************************************/ diff --git a/libretroshare/src/services/p3chatservice.cc b/libretroshare/src/services/p3chatservice.cc index f81f6561e..1dd1c639c 100644 --- a/libretroshare/src/services/p3chatservice.cc +++ b/libretroshare/src/services/p3chatservice.cc @@ -24,6 +24,7 @@ */ #include "util/rsdir.h" +#include "rsiface/rsiface.h" #include "pqi/pqibin.h" #include "pqi/pqinotify.h" #include "pqi/pqiarchive.h" @@ -90,7 +91,7 @@ int p3ChatService::sendChat(std::wstring msg) for(it = ids.begin(); it != ids.end(); it++) { - RsChatItem *ci = new RsChatItem(); + RsChatMsgItem *ci = new RsChatMsgItem(); ci->PeerId(*it); ci->chatFlags = 0; @@ -170,7 +171,21 @@ class p3ChatService::AvatarInfo }; -int p3ChatService::sendPrivateChat(std::wstring msg, std::string id) +void p3ChatService::sendStatusString( const std::string& id , const std::string& status_string) +{ + RsChatStatusItem *cs = new RsChatStatusItem ; + + cs->status_string = status_string ; + cs->PeerId(id); + +#ifdef CHAT_DEBUG + std::cerr << "sending chat status packet:" << std::endl ; + cs->print(std::cerr) ; +#endif + sendItem(cs); +} + +int p3ChatService::sendPrivateChat( std::wstring msg, std::string id) { // make chat item.... #ifdef CHAT_DEBUG @@ -178,7 +193,7 @@ int p3ChatService::sendPrivateChat(std::wstring msg, std::string id) std::cerr << std::endl; #endif - RsChatItem *ci = new RsChatItem(); + RsChatMsgItem *ci = new RsChatMsgItem(); ci->PeerId(id); ci->chatFlags = RS_CHAT_FLAG_PRIVATE; @@ -215,50 +230,70 @@ int p3ChatService::sendPrivateChat(std::wstring msg, std::string id) return 1; } -std::list p3ChatService::getChatQueue() +std::list p3ChatService::getChatQueue() { time_t now = time(NULL); - RsChatItem *ci = NULL; - std::list ilist; + RsItem *item ; + std::list ilist; - while(NULL != (ci = (RsChatItem *) recvItem())) + while(NULL != (item=recvItem())) { #ifdef CHAT_DEBUG - std::cerr << "p3ChatService::getChatQueue() Item:"; - std::cerr << std::endl; - ci->print(std::cerr); - std::cerr << std::endl; - std::cerr << "Got msg. Flags = " << ci->chatFlags << std::endl ; + std::cerr << "p3ChatService::getChatQueue() Item:" << (void*)item << std::endl ; +#endif + RsChatMsgItem *ci = dynamic_cast(item) ; + + if(ci != NULL) + { +#ifdef CHAT_DEBUG + std::cerr << "p3ChatService::getChatQueue() Item:"; + std::cerr << std::endl; + ci->print(std::cerr); + std::cerr << std::endl; + std::cerr << "Got msg. Flags = " << ci->chatFlags << std::endl ; #endif - if(ci->chatFlags & RS_CHAT_FLAG_CONTAINS_AVATAR) // no msg here. Just an avatar. - receiveAvatarJpegData(ci) ; - else if(ci->chatFlags & RS_CHAT_FLAG_REQUESTS_AVATAR) // no msg here. Just an avatar request. - sendAvatarJpegData(ci->PeerId()) ; - else // normal msg. Return it normally. - { - // Check if new avatar is available at peer's. If so, send a request to get the avatar. - if(ci->chatFlags & RS_CHAT_FLAG_AVATAR_AVAILABLE) - { - std::cerr << "New avatar is available for peer " << ci->PeerId() << ", sending request" << std::endl ; - sendAvatarRequest(ci->PeerId()) ; - ci->chatFlags &= ~RS_CHAT_FLAG_AVATAR_AVAILABLE ; - } - - std::map::const_iterator it = _avatars.find(ci->PeerId()) ; - - std::cerr << "p3chatservice:: avatar requested from above. " << std::endl ; - // has avatar. Return it strait away. - // - if(it!=_avatars.end() && it->second->_peer_is_new) + if(ci->chatFlags & RS_CHAT_FLAG_CONTAINS_AVATAR) // no msg here. Just an avatar. + receiveAvatarJpegData(ci) ; + else if(ci->chatFlags & RS_CHAT_FLAG_REQUESTS_AVATAR) // no msg here. Just an avatar request. + sendAvatarJpegData(ci->PeerId()) ; + else // normal msg. Return it normally. { - std::cerr << "Adatar is new for peer. ending info above" << std::endl ; - ci->chatFlags |= RS_CHAT_FLAG_AVATAR_AVAILABLE ; - } + // Check if new avatar is available at peer's. If so, send a request to get the avatar. + if(ci->chatFlags & RS_CHAT_FLAG_AVATAR_AVAILABLE) + { + std::cerr << "New avatar is available for peer " << ci->PeerId() << ", sending request" << std::endl ; + sendAvatarRequest(ci->PeerId()) ; + ci->chatFlags &= ~RS_CHAT_FLAG_AVATAR_AVAILABLE ; + } - ci->recvTime = now; - ilist.push_back(ci); + std::map::const_iterator it = _avatars.find(ci->PeerId()) ; + + std::cerr << "p3chatservice:: avatar requested from above. " << std::endl ; + // has avatar. Return it strait away. + // + if(it!=_avatars.end() && it->second->_peer_is_new) + { + std::cerr << "Adatar is new for peer. ending info above" << std::endl ; + ci->chatFlags |= RS_CHAT_FLAG_AVATAR_AVAILABLE ; + } + + ci->recvTime = now; + ilist.push_back(ci); + } + } + RsChatStatusItem *cs = dynamic_cast(item) ; + + if(cs != NULL) + { + // we should notify for a status string for the current peer. +#ifdef CHAT_DEBUG + std::cerr << "Received status string \"" << cs->status_string << "\"" << std::endl ; +#endif + rsicontrol->getNotify().notifyChatStatus(cs->PeerId(),cs->status_string) ; + + delete item ; } } @@ -284,7 +319,7 @@ void p3ChatService::setOwnAvatarJpegData(const unsigned char *data,int size) IndicateConfigChanged(); } -void p3ChatService::receiveAvatarJpegData(RsChatItem *ci) +void p3ChatService::receiveAvatarJpegData(RsChatMsgItem *ci) { RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ std::cerr << "p3chatservice: received avatar jpeg data for peer " << ci->PeerId() << ". Storing it." << std::endl ; @@ -339,7 +374,7 @@ void p3ChatService::sendAvatarRequest(const std::string& peer_id) { // Doesn't have avatar. Request it. // - RsChatItem *ci = new RsChatItem(); + RsChatMsgItem *ci = new RsChatMsgItem(); ci->PeerId(peer_id); ci->chatFlags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_REQUESTS_AVATAR ; @@ -352,10 +387,10 @@ void p3ChatService::sendAvatarRequest(const std::string& peer_id) sendItem(ci); } -RsChatItem *p3ChatService::makeOwnAvatarItem() +RsChatMsgItem *p3ChatService::makeOwnAvatarItem() { RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - RsChatItem *ci = new RsChatItem(); + RsChatMsgItem *ci = new RsChatMsgItem(); ci->chatFlags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_CONTAINS_AVATAR ; ci->sendTime = time(NULL); @@ -371,7 +406,7 @@ void p3ChatService::sendAvatarJpegData(const std::string& peer_id) if(_own_avatar != NULL) { - RsChatItem *ci = makeOwnAvatarItem(); + RsChatMsgItem *ci = makeOwnAvatarItem(); ci->PeerId(peer_id); // take avatar, and embed it into a std::wstring. @@ -396,11 +431,11 @@ bool p3ChatService::loadConfiguration(std::string &loadHash) BinFileInterface *in = new BinFileInterface(msgfile.c_str(), BIN_FLAGS_READABLE | BIN_FLAGS_HASH_DATA); pqiarchive *pa_in = new pqiarchive(rss, in, BIN_FLAGS_READABLE); RsItem *item; - RsChatItem *mitem; + RsChatMsgItem *mitem; while((item = pa_in -> GetItem())) { - if(NULL != (mitem = dynamic_cast(item))) + if(NULL != (mitem = dynamic_cast(item))) { RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ @@ -451,7 +486,7 @@ bool p3ChatService::saveConfiguration() if(_own_avatar != NULL) { std::cerr << "Saving avatar config to file " << msgfile << std::endl ; - RsChatItem *ci = makeOwnAvatarItem() ; + RsChatMsgItem *ci = makeOwnAvatarItem() ; ci->PeerId(mConnMgr->getOwnId()); if(!pa_out -> SendItem(ci)) diff --git a/libretroshare/src/services/p3chatservice.h b/libretroshare/src/services/p3chatservice.h index 0232cf048..96ac9879f 100644 --- a/libretroshare/src/services/p3chatservice.h +++ b/libretroshare/src/services/p3chatservice.h @@ -50,6 +50,7 @@ class p3ChatService: public p3Service, public pqiConfig int sendChat(std::wstring msg); int sendPrivateChat(std::wstring msg, std::string id); + void sendStatusString(const std::string& peer_id,const std::string& status_str) ; /// gets the peer's avatar in jpeg format, if available. Null otherwise. Also asks the peer to send /// its avatar, if not already available. Creates a new unsigned char array. It's the caller's @@ -61,7 +62,7 @@ class p3ChatService: public p3Service, public pqiConfig void setOwnAvatarJpegData(const unsigned char *data,int size) ; void getOwnAvatarJpegData(unsigned char *& data,int& size) ; - std::list getChatQueue(); + std::list getChatQueue(); /*** Overloaded from pqiConfig ****/ virtual bool loadConfiguration(std::string &loadHash); @@ -76,12 +77,12 @@ class p3ChatService: public p3Service, public pqiConfig void sendAvatarJpegData(const std::string& peer_id) ; /// Receive the avatar in a chat item, with RS_CHAT_RECEIVE_AVATAR flag. - void receiveAvatarJpegData(RsChatItem *ci) ; + void receiveAvatarJpegData(RsChatMsgItem *ci) ; /// Sends a request for an avatar to the peer of given id void sendAvatarRequest(const std::string& peer_id) ; - RsChatItem *makeOwnAvatarItem() ; + RsChatMsgItem *makeOwnAvatarItem() ; p3ConnectMgr *mConnMgr; diff --git a/retroshare-gui/src/gui/ChatDialog.cpp b/retroshare-gui/src/gui/ChatDialog.cpp deleted file mode 100644 index 088fa8212..000000000 --- a/retroshare-gui/src/gui/ChatDialog.cpp +++ /dev/null @@ -1,529 +0,0 @@ -/**************************************************************** - * RetroShare is distributed under the following license: - * - * Copyright (C) 2006, crypton - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - ****************************************************************/ -#include - -#include "rshare.h" -#include "ChatDialog.h" - -#include "rsiface/rsiface.h" -#include "rsiface/rspeers.h" -#include "rsiface/rsmsgs.h" -#include "rsiface/rsnotify.h" - -#include "chat/PopupChatDialog.h" -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/** Constructor */ -ChatDialog::ChatDialog(QWidget *parent) -: MainPage (parent) -{ - /* Invoke the Qt Designer generated object setup routine */ - ui.setupUi(this); - - loadEmoticonsgroupchat(); - - setWindowIcon(QIcon(QString(":/images/rstray3.png"))); - - connect(ui.lineEdit, SIGNAL(textChanged ( ) ), this, SLOT(checkChat( ) )); - connect(ui.Sendbtn, SIGNAL(clicked()), this, SLOT(sendMsg())); - connect(ui.emoticonBtn, SIGNAL(clicked()), this, SLOT(smileyWidgetgroupchat())); - - - connect( ui.msgSendList, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( msgSendListCostumPopupMenu( QPoint ) ) ); - connect( ui.msgText, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayInfoChatMenu(const QPoint&))); - - connect(ui.textboldChatButton, SIGNAL(clicked()), this, SLOT(setFont())); - connect(ui.textunderlineChatButton, SIGNAL(clicked()), this, SLOT(setFont())); - connect(ui.textitalicChatButton, SIGNAL(clicked()), this, SLOT(setFont())); - connect(ui.fontsButton, SIGNAL(clicked()), this, SLOT(getFont())); - connect(ui.colorChatButton, SIGNAL(clicked()), this, SLOT(setColor())); - - ui.fontsButton->setIcon(QIcon(QString(":/images/fonts.png"))); - -// connect(ui.msgSendList, SIGNAL(itemChanged( QTreeWidgetItem *, int ) ), -// this, SLOT(toggleSendItem( QTreeWidgetItem *, int ) )); - - - /* hide the Tree +/- */ - ui.msgSendList -> setRootIsDecorated( false ); - - /* to hide the header */ - ui.msgSendList->header()->hide(); - - _currentColor = Qt::black; - QPixmap pxm(24,24); - pxm.fill(_currentColor); - ui.colorChatButton->setIcon(pxm); - - //QFont font = QFont("Comic Sans MS", 10); - mCurrentFont = QFont("Comic Sans MS", 12); - ui.lineEdit->setFont(mCurrentFont); - - setChatInfo(tr("Welcome to RetroShare's group chat."), QString::fromUtf8("blue")); - - QMenu * grpchatmenu = new QMenu(); - grpchatmenu->addAction(ui.actionClearChat); - ui.menuButton->setMenu(grpchatmenu); - - _underline = false; - - QTimer *timer = new QTimer(this); - timer->connect(timer, SIGNAL(timeout()), this, SLOT(insertChat())); - timer->start(500); /* half a second */ - - /* Hide platform specific features */ -#ifdef Q_WS_WIN - -#endif -} - -void ChatDialog::msgSendListCostumPopupMenu( QPoint point ) -{ - - QMenu contextMnu( this ); - QMouseEvent *mevent = new QMouseEvent( QEvent::MouseButtonPress, point, Qt::RightButton, Qt::RightButton, Qt::NoModifier ); - - privchatAct = new QAction(QIcon(), tr( "Chat" ), this ); - connect( privchatAct , SIGNAL( triggered() ), this, SLOT( privchat() ) ); - - contextMnu.clear(); - contextMnu.addAction( privchatAct); - contextMnu.exec( mevent->globalPos() ); -} - -void ChatDialog::insertChat() -{ - if (!rsMsgs->chatAvailable()) - { - return; - } - - std::list newchat; - if (!rsMsgs->getNewChat(newchat)) - { - return; - } - - QTextEdit *msgWidget = ui.msgText; - std::list::iterator it; - - - /** A RshareSettings object used for saving/loading settings */ - RshareSettings settings; - uint chatflags = settings.getChatFlags(); - - /* add in lines at the bottom */ - for(it = newchat.begin(); it != newchat.end(); it++) - { - std::string msg(it->msg.begin(), it->msg.end()); - std::cerr << "ChatDialog::insertChat(): " << msg << std::endl; - - /* are they private? */ - if (it->chatflags & RS_CHAT_PRIVATE) - { - std::cerr << "ChatDialog::insert(Private)Chat(): "; - std::cerr << "Flags(" << chatflags << ") " << msg << std::endl; - - PopupChatDialog *pcd = getPrivateChat(it->rsid, it->name, chatflags); - pcd->addChatMsg(&(*it)); - continue; - } - - std::ostringstream out; - QString currenttxt = msgWidget->toHtml(); - QString extraTxt; - - QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss"); - QString name = QString::fromStdString(it->name); - QString line = "" + timestamp + "" + - "" + " " + name + ""; - - extraTxt += line; - - extraTxt += QString::fromStdWString(it->msg); - - /* add it everytime */ - currenttxt += extraTxt; - - QHashIterator i(smileys); - while(i.hasNext()) - { - i.next(); - currenttxt.replace(i.key(), ""); - } - - - msgWidget->setHtml(currenttxt); - - - QScrollBar *qsb = msgWidget->verticalScrollBar(); - qsb -> setValue(qsb->maximum()); - } -} - -void ChatDialog::checkChat() -{ - /* if at the end of the text -> we can send it! */ - QTextEdit *chatWidget = ui.lineEdit; - std::string txt = chatWidget->toPlainText().toStdString(); - if ('\n' == txt[txt.length()-1]) - { - //std::cerr << "Found found at end of :" << txt << ": should send!"; - //std::cerr << std::endl; - if (txt.length()-1 == txt.find('\n')) /* only if on first line! */ - { - /* should remove last char ... */ - sendMsg(); - } - } - else - { - //std::cerr << "No found in :" << txt << ":"; - //std::cerr << std::endl; - } -} - -void ChatDialog::sendMsg() -{ - QTextEdit *lineWidget = ui.lineEdit; - - ChatInfo ci; - //ci.msg = lineWidget->Text().toStdWString(); - ci.msg = lineWidget->toHtml().toStdWString(); - ci.chatflags = RS_CHAT_PUBLIC; - - std::string msg(ci.msg.begin(), ci.msg.end()); - //std::cerr << "ChatDialog::sendMsg(): " << msg << std::endl; - - rsMsgs -> ChatSend(ci); - ui.lineEdit->clear(); - setFont(); - - /* redraw send list */ - insertSendList(); - -} - -void ChatDialog::insertSendList() -{ - std::list peers; - std::list::iterator it; - - if (!rsPeers) - { - /* not ready yet! */ - return; - } - - rsPeers->getOnlineList(peers); - - /* get a link to the table */ - QTreeWidget *sendWidget = ui.msgSendList; - QList items; - - for(it = peers.begin(); it != peers.end(); it++) - { - - RsPeerDetails details; - if (!rsPeers->getPeerDetails(*it, details)) - { - continue; /* BAD */ - } - - /* make a widget per friend */ - QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0); - - /* add all the labels */ - /* (0) Person */ - item -> setText(0, QString::fromStdString(details.name)); - - item -> setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); - //item -> setFlags(Qt::ItemIsUserCheckable); - - item -> setCheckState(0, Qt::Checked); - - if (rsicontrol->IsInChat(*it)) - { - item -> setCheckState(0, Qt::Checked); - } - else - { - item -> setCheckState(0, Qt::Unchecked); - } - - /* disable for the moment */ - item -> setFlags(Qt::ItemIsUserCheckable); - item -> setCheckState(0, Qt::Checked); - - /* add to the list */ - items.append(item); - } - - /* remove old items */ - sendWidget->clear(); - sendWidget->setColumnCount(1); - - /* add the items in! */ - sendWidget->insertTopLevelItems(0, items); - - sendWidget->update(); /* update display */ -} - - -/* to toggle the state */ - - -void ChatDialog::toggleSendItem( QTreeWidgetItem *item, int col ) -{ - //std::cerr << "ToggleSendItem()" << std::endl; - - /* extract id */ - std::string id = (item -> text(4)).toStdString(); - - /* get state */ - bool inChat = (Qt::Checked == item -> checkState(0)); /* alway column 0 */ - - /* call control fns */ - - rsicontrol -> SetInChat(id, inChat); - return; -} - -void ChatDialog::privchat() -{ - -} - - - -PopupChatDialog *ChatDialog::getPrivateChat(std::string id, std::string name, uint chatflags) -{ - /* see if it exists already */ - PopupChatDialog *popupchatdialog = NULL; - bool show = false; - - if (chatflags & RS_CHAT_REOPEN) - { - show = true; - std::cerr << "reopen flag so: enable SHOW popupchatdialog()"; - std::cerr << std::endl; - } - - - std::map::iterator it; - if (chatDialogs.end() != (it = chatDialogs.find(id))) - { - /* exists already */ - popupchatdialog = it->second; - } - else - { - popupchatdialog = new PopupChatDialog(id, name); - chatDialogs[id] = popupchatdialog; - - if (chatflags & RS_CHAT_OPEN_NEW) - { - std::cerr << "new chat so: enable SHOW popupchatdialog()"; - std::cerr << std::endl; - - show = true; - } - } - - if (show) - { - std::cerr << "SHOWING popupchatdialog()"; - std::cerr << std::endl; - - popupchatdialog->show(); - } - - /* now only do these if the window is visible */ - if (popupchatdialog->isVisible()) - { - if (chatflags & RS_CHAT_FOCUS) - { - std::cerr << "focus chat flag so: GETFOCUS popupchatdialog()"; - std::cerr << std::endl; - - popupchatdialog->getfocus(); - } - else - { - std::cerr << "no focus chat flag so: FLASH popupchatdialog()"; - std::cerr << std::endl; - - popupchatdialog->flash(); - } - } - else - { - std::cerr << "not visible ... so leave popupchatdialog()"; - std::cerr << std::endl; - } - - return popupchatdialog; -} - -void ChatDialog::clearOldChats() -{ - /* nothing yet */ - -} - -void ChatDialog::setColor() -{ - - bool ok; - QRgb color = QColorDialog::getRgba(ui.lineEdit->textColor().rgba(), &ok, this); - if (ok) { - _currentColor = QColor(color); - QPixmap pxm(24,24); - pxm.fill(_currentColor); - ui.colorChatButton->setIcon(pxm); - } - setFont(); -} - -void ChatDialog::getFont() -{ - bool ok; - mCurrentFont = QFontDialog::getFont(&ok, mCurrentFont, this); - setFont(); -} - -void ChatDialog::setFont() -{ - mCurrentFont.setBold(ui.textboldChatButton->isChecked()); - mCurrentFont.setUnderline(ui.textunderlineChatButton->isChecked()); - mCurrentFont.setItalic(ui.textitalicChatButton->isChecked()); - ui.lineEdit->setFont(mCurrentFont); - ui.lineEdit->setTextColor(_currentColor); - - ui.lineEdit->setFocus(); - -} - -void ChatDialog::underline() -{ - _underline = !_underline; - ui.lineEdit->setFontUnderline(_underline); -} - - -// Update Chat Info information -void ChatDialog::setChatInfo(QString info, QColor color) -{ - static unsigned int nbLines = 0; - ++nbLines; - // Check log size, clear it if too big - if(nbLines > 200) { - ui.msgText->clear(); - nbLines = 1; - } - ui.msgText->append(QString::fromUtf8("")+ QTime::currentTime().toString(QString::fromUtf8("hh:mm:ss")) + QString::fromUtf8(" - ") + info + QString::fromUtf8("")); -} - -void ChatDialog::on_actionClearChat_triggered() -{ - ui.msgText->clear(); -} - -void ChatDialog::displayInfoChatMenu(const QPoint& pos) -{ - // Log Menu - QMenu myChatMenu(this); - myChatMenu.addAction(ui.actionClearChat); - // XXX: Why mapToGlobal() is not enough? - myChatMenu.exec(mapToGlobal(pos)+QPoint(0,80)); -} - -void ChatDialog::loadEmoticonsgroupchat() -{ - QDir smdir(QApplication::applicationDirPath() + "/emoticons/kopete"); - QFileInfoList sminfo = smdir.entryInfoList(QStringList() << "*.gif" << "*.png", QDir::Files, QDir::Name); - foreach(QFileInfo info, sminfo) - { - QString smcode = info.fileName().replace(".gif", ""); - QString smstring; - for(int i = 0; i < 9; i+=3) - { - smstring += QString((char)smcode.mid(i,3).toInt()); - } - //qDebug(smstring.toAscii()); - smileys.insert(smstring, info.absoluteFilePath()); - } -} - -void ChatDialog::smileyWidgetgroupchat() -{ - qDebug("MainWindow::smileyWidget()"); - QWidget *smWidget = new QWidget; - smWidget->setWindowTitle("Emoticons"); - smWidget->setWindowIcon(QIcon(QString(":/images/rstray3.png"))); - smWidget->setFixedSize(256,256); - - - - int x = 0, y = 0; - - QHashIterator i(smileys); - while(i.hasNext()) - { - i.next(); - QPushButton *smButton = new QPushButton("", smWidget); - smButton->setGeometry(x*24, y*24, 24,24); - smButton->setIconSize(QSize(24,24)); - smButton->setIcon(QPixmap(i.value())); - smButton->setToolTip(i.key()); - //smButton->setFixedSize(24,24); - ++x; - if(x > 4) - { - x = 0; - y++; - } - connect(smButton, SIGNAL(clicked()), this, SLOT(addSmileys())); - } - - smWidget->show(); -} - -void ChatDialog::addSmileys() -{ - ui.lineEdit->setText(ui.lineEdit->toHtml() + qobject_cast(sender())->toolTip()); -} diff --git a/retroshare-gui/src/gui/ChatDialog.h b/retroshare-gui/src/gui/ChatDialog.h deleted file mode 100644 index 22c1f7c80..000000000 --- a/retroshare-gui/src/gui/ChatDialog.h +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************** - * RetroShare is distributed under the following license: - * - * Copyright (C) 2006, crypton - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - ****************************************************************/ - -#ifndef _CHATDIALOG_H -#define _CHATDIALOG_H - -#include "mainpage.h" -#include "ui_ChatDialog.h" - -#include "chat/PopupChatDialog.h" - -class QFont; -class QAction; -class QTextEdit; -class QTextCharFormat; - -class ChatDialog : public MainPage -{ - Q_OBJECT - -public: - /** Default Constructor */ - ChatDialog(QWidget *parent = 0); - /** Default Destructor */ - - PopupChatDialog *getPrivateChat(std::string id, std::string name, uint chatflags); - void clearOldChats(); - - void loadEmoticonsgroupchat(); - - - -public slots: - - void insertChat(); - void setChatInfo(QString info, QColor color=QApplication::palette().color(QPalette::WindowText)); - - void smileyWidgetgroupchat(); - void addSmileys(); - -private slots: - -void toggleSendItem( QTreeWidgetItem *item, int col ); - - /** Create the context popup menu and it's submenus */ - void msgSendListCostumPopupMenu( QPoint point ); - - void setColor(); - void insertSendList(); - void checkChat(); - void sendMsg(); - - void privchat(); - - void setFont(); - void getFont(); - void underline(); - - - - void on_actionClearChat_triggered(); - void displayInfoChatMenu(const QPoint& pos); - - -private: - - QAction *actionTextBold; - QAction *actionTextUnderline; - QAction *actionTextItalic; - - /** Define the popup menus for the Context menu */ - QMenu* contextMnu; - /** Defines the actions for the context menu */ - QAction* privchatAct; - - QTreeView *msgSendList; - - // QColor textColor; - QColor _currentColor; - bool _underline; - - QHash smileys; - - std::map chatDialogs; - - QFont mCurrentFont; /* how the text will come out */ - - /** Qt Designer generated object */ - Ui::ChatDialog ui; -}; - -#endif - diff --git a/retroshare-gui/src/gui/PeersDialog.h b/retroshare-gui/src/gui/PeersDialog.h index 15e16041c..264828db2 100644 --- a/retroshare-gui/src/gui/PeersDialog.h +++ b/retroshare-gui/src/gui/PeersDialog.h @@ -50,7 +50,7 @@ public: void clearOldChats(); void loadEmoticonsgroupchat(); - void setChatDialog(ChatDialog *cd); +// void setChatDialog(ChatDialog *cd); public slots: @@ -72,6 +72,8 @@ private slots: /** Create the context popup menu and it's submenus */ void peertreeWidgetCostumPopupMenu( QPoint point ); + void updatePeerStatusString(const QString& peer_id,const QString& chat_status) ; + /** Export friend in Friends Dialog */ void exportfriend(); /** Remove friend */ @@ -109,7 +111,7 @@ private: /* (2) Utility Fns */ QTreeWidgetItem *getCurrentPeer(); - ChatDialog *chatDialog; + // ChatDialog *chatDialog; /** Define the popup menus for the Context menu */ diff --git a/retroshare-gui/src/gui/chat/PopupChatDialog.cpp b/retroshare-gui/src/gui/chat/PopupChatDialog.cpp index 47f90a49c..3cb0d71b4 100644 --- a/retroshare-gui/src/gui/chat/PopupChatDialog.cpp +++ b/retroshare-gui/src/gui/chat/PopupChatDialog.cpp @@ -63,6 +63,7 @@ PopupChatDialog::PopupChatDialog(std::string id, std::string name, loadEmoticons(); + last_status_send_time = 0 ; styleHtm = appDir + "/style/chat/default.htm"; /* Hide Avatar frame */ @@ -85,9 +86,8 @@ PopupChatDialog::PopupChatDialog(std::string id, std::string name, connect(ui.styleButton, SIGNAL(clicked()), SLOT(changeStyle())); // Create the status bar - std::ostringstream statusstr; - statusstr << "Chatting with " << dialogName << " (" << id << ")" ; - statusBar()->showMessage(QString::fromStdString(statusstr.str())); + resetStatusBar() ; + ui.textBrowser->setOpenExternalLinks ( false ); QString title = QString::fromStdString(name) + " :" + tr(" RetroShare - Encrypted Chat") ; @@ -129,6 +129,30 @@ PopupChatDialog::PopupChatDialog(std::string id, std::string name, updatePeerAvatar(id) ; } +void PopupChatDialog::resetStatusBar() +{ + statusBar()->showMessage(QString("Chatting with ") + QString::fromStdString(dialogName) + " (" +QString::fromStdString(dialogId)+ ")") ; +} + +void PopupChatDialog::updateStatusTyping() +{ + if(time(NULL) - last_status_send_time > 5) // limit 'peer is typing' packets to at most every 10 sec + { + rsMsgs->sendStatusString(dialogId, rsiface->getConfig().ownName + " is typing..."); + last_status_send_time = time(NULL) ; + } +} + +// Called by libretroshare through notifyQt to display the peer's status +// +void PopupChatDialog::updateStatusString(const QString& status_string) +{ + statusBar()->showMessage(status_string,2000) ; // displays info for 5 secs. + + QTimer::singleShot(2000,this,SLOT(resetStatusBar())) ; +} + + /** Destructor. */ PopupChatDialog::~PopupChatDialog() { @@ -259,23 +283,12 @@ void PopupChatDialog::addChatMsg(ChatInfo *ci) void PopupChatDialog::checkChat() { /* if at the end of the text -> we can send it! */ - QTextEdit *chatWidget = ui.chattextEdit; - std::string txt = chatWidget->toPlainText().toStdString(); - if ('\n' == txt[txt.length()-1]) - { - //std::cerr << "Found found at end of :" << txt << ": should send!"; - //std::cerr << std::endl; - if (txt.length()-1 == txt.find('\n')) /* only if on first line! */ - { - /* should remove last char ... */ - sendChat(); - } - } + QTextEdit *chatWidget = ui.chattextEdit; + std::string txt = chatWidget->toPlainText().toStdString(); + if ('\n' == txt[txt.length()-1] && txt.length()-1 == txt.find('\n')) /* only if on first line! */ + sendChat(); else - { - //std::cerr << "No found in :" << txt << ":"; - //std::cerr << std::endl; - } + updateStatusTyping() ; } diff --git a/retroshare-gui/src/gui/chat/PopupChatDialog.h b/retroshare-gui/src/gui/chat/PopupChatDialog.h index 2a55f5262..9e34c9e57 100644 --- a/retroshare-gui/src/gui/chat/PopupChatDialog.h +++ b/retroshare-gui/src/gui/chat/PopupChatDialog.h @@ -75,6 +75,9 @@ public slots: void changeStyle(); + void resetStatusBar() ; + void updateStatusTyping() ; + void updateStatusString(const QString&) ; protected: void closeEvent (QCloseEvent * event); @@ -107,6 +110,7 @@ private: unsigned int lastChatTime; std::string lastChatName; + time_t last_status_send_time ; QHash smileys; QColor mCurrentColor; QFont mCurrentFont; diff --git a/retroshare-gui/src/main.cpp b/retroshare-gui/src/main.cpp index bc8c71a22..970e97408 100644 --- a/retroshare-gui/src/main.cpp +++ b/retroshare-gui/src/main.cpp @@ -122,7 +122,6 @@ int main(int argc, char *argv[]) RsIface *iface = createRsIface(*notify); RsControl *rsServer = createRsControl(*iface, *notify); - notify->setRsIface(iface); /* save to the global variables */ rsiface = iface; @@ -140,14 +139,17 @@ int main(int argc, char *argv[]) //skinWindow->setCentralWidget(w); /* Attach the Dialogs, to the Notify Class */ - notify->setNetworkDialog(w->networkDialog); - notify->setPeersDialog(w->peersDialog); - notify->setDirDialog(w->sharedfilesDialog); - notify->setTransfersDialog(w->transfersDialog); - notify->setChatDialog(w->chatDialog); - notify->setMessagesDialog(w->messagesDialog); - notify->setChannelsDialog(w->channelsDialog); - notify->setMessengerWindow(w->messengerWindow); +// Not needed anymore since the notify class is directly connected by Qt signals/slots to the correct widgets below. +// +// notify->setRsIface(iface); +// notify->setNetworkDialog(w->networkDialog); +// notify->setPeersDialog(w->peersDialog); +// notify->setDirDialog(w->sharedfilesDialog); +// notify->setTransfersDialog(w->transfersDialog); +// notify->setChatDialog(w->chatDialog); +// notify->setMessagesDialog(w->messagesDialog); +// notify->setChannelsDialog(w->channelsDialog); +// notify->setMessengerWindow(w->messengerWindow); // I'm using a signal to transfer the hashing info to the mainwindow, because Qt schedules signals properly to // avoid clashes between infos from threads. @@ -167,6 +169,8 @@ int main(int argc, char *argv[]) QObject::connect(notify,SIGNAL(messagesChanged()) ,w->messagesDialog ,SLOT(insertMessages() )) ; QObject::connect(notify,SIGNAL(configChanged()) ,w->messagesDialog ,SLOT(displayConfig() )) ; + QObject::connect(notify,SIGNAL(chatStatusChanged(const QString&,const QString&)),w->peersDialog,SLOT(updatePeerStatusString(const QString&,const QString&))); + /* only show window, if not startMinimized */ if (!startMinimised) { diff --git a/retroshare-gui/src/rsiface/notifyqt.cpp b/retroshare-gui/src/rsiface/notifyqt.cpp index f7f6909ac..7ae3ad57a 100644 --- a/retroshare-gui/src/rsiface/notifyqt.cpp +++ b/retroshare-gui/src/rsiface/notifyqt.cpp @@ -39,16 +39,19 @@ void NotifyQt::notifyErrorMsg(int list, int type, std::string msg) return; } +void NotifyQt::notifyChatStatus(const std::string& peer_id,const std::string& status_string) +{ + std::cerr << "Received chat status string: " << status_string << std::endl ; + emit chatStatusChanged(QString::fromStdString(peer_id),QString::fromStdString(status_string)) ; +} + #ifdef TURTLE_HOPPING void NotifyQt::notifyTurtleSearchResult(uint32_t search_id,const std::list& files) { std::cerr << "in notify search result..." << std::endl ; -// QList qfiles ; - for(std::list::const_iterator it(files.begin());it!=files.end();++it) emit gotTurtleSearchResult(search_id,*it) ; -// qfiles.push_back(*it) ; } #endif void NotifyQt::notifyHashingInfo(std::string fileinfo) @@ -56,10 +59,11 @@ void NotifyQt::notifyHashingInfo(std::string fileinfo) emit hashingInfoChanged(QString::fromStdString(fileinfo)) ; } -void NotifyQt::notifyChat() -{ - return; -} +//void NotifyQt::notifyChat() +//{ +// std::cerr << "Received chat notification" << std::endl ; +// return; +//} void NotifyQt::notifyListChange(int list, int type) { @@ -90,7 +94,6 @@ void NotifyQt::notifyListChange(int list, int type) emit filesPostModChanged(true) ; /* Local */ break; case NOTIFY_LIST_SEARCHLIST: - //displaySearch(); break; case NOTIFY_LIST_MESSAGELIST: #ifdef DEBUG @@ -99,7 +102,6 @@ void NotifyQt::notifyListChange(int list, int type) emit messagesChanged() ; break; case NOTIFY_LIST_CHANNELLIST: - //displayChannels(); break; case NOTIFY_LIST_TRANSFERLIST: #ifdef DEBUG @@ -128,7 +130,6 @@ void NotifyQt::notifyListPreChange(int list, int type) switch(list) { case NOTIFY_LIST_NEIGHBOURS: - //preDisplayNeighbours(); break; case NOTIFY_LIST_FRIENDS: emit friendsChanged() ; @@ -138,16 +139,12 @@ void NotifyQt::notifyListPreChange(int list, int type) emit filesPreModChanged(true) ; /* local */ break; case NOTIFY_LIST_SEARCHLIST: - //preDisplaySearch(); break; case NOTIFY_LIST_MESSAGELIST: - //preDisplayMessages(); break; case NOTIFY_LIST_CHANNELLIST: - //preDisplayChannels(); break; case NOTIFY_LIST_TRANSFERLIST: - //preDisplayTransfers(); break; default: break; @@ -176,7 +173,7 @@ void NotifyQt::UpdateGUI() if (time(NULL) > lastTs + 5) // update every 5 seconds. I don't know what to do with these. { - displayChannels(); +// displayChannels(); } lastTs = time(NULL) ; @@ -273,88 +270,88 @@ void NotifyQt::UpdateGUI() } } -void NotifyQt::displaySearch() -{ - iface->lockData(); /* Lock Interface */ +//void NotifyQt::displaySearch() +//{ +// iface->lockData(); /* Lock Interface */ +// +//#ifdef NOTIFY_DEBUG +// std::ostringstream out; +// std::cerr << out.str(); +//#endif +// +// iface->unlockData(); /* UnLock Interface */ +//} -#ifdef NOTIFY_DEBUG - std::ostringstream out; - std::cerr << out.str(); -#endif +// void NotifyQt::displayChat() +// { +// iface->lockData(); /* Lock Interface */ +// +// #ifdef NOTIFY_DEBUG +// std::ostringstream out; +// std::cerr << out.str(); +// #endif +// +// iface->unlockData(); /* UnLock Interface */ +// +// if (hDialog) +// hDialog -> insertChat(); +// } +// +// +//void NotifyQt::displayChannels() +//{ +// iface->lockData(); /* Lock Interface */ +// +//#ifdef NOTIFY_DEBUG +// std::ostringstream out; +// std::cerr << out.str(); +//#endif +// +// iface->unlockData(); /* UnLock Interface */ +// +// if (sDialog) +// sDialog -> insertChannels(); +//} +// +// +//void NotifyQt::displayTransfers() +//{ +// /* Do the GUI */ +// if (tDialog) +// tDialog->insertTransfers(); +//} +// +// +//void NotifyQt::preDisplayNeighbours() +//{ +// +//} +// +//void NotifyQt::preDisplayFriends() +//{ +// +//} - iface->unlockData(); /* UnLock Interface */ -} - -void NotifyQt::displayChat() -{ - iface->lockData(); /* Lock Interface */ - -#ifdef NOTIFY_DEBUG - std::ostringstream out; - std::cerr << out.str(); -#endif - - iface->unlockData(); /* UnLock Interface */ - - if (hDialog) - hDialog -> insertChat(); -} - - -void NotifyQt::displayChannels() -{ - iface->lockData(); /* Lock Interface */ - -#ifdef NOTIFY_DEBUG - std::ostringstream out; - std::cerr << out.str(); -#endif - - iface->unlockData(); /* UnLock Interface */ - - if (sDialog) - sDialog -> insertChannels(); -} - - -void NotifyQt::displayTransfers() -{ - /* Do the GUI */ - if (tDialog) - tDialog->insertTransfers(); -} - - -void NotifyQt::preDisplayNeighbours() -{ - -} - -void NotifyQt::preDisplayFriends() -{ - -} - -void NotifyQt::preDisplaySearch() -{ - -} - -void NotifyQt::preDisplayMessages() -{ - -} - -void NotifyQt::preDisplayChannels() -{ - -} - -void NotifyQt::preDisplayTransfers() -{ - - -} +//void NotifyQt::preDisplaySearch() +//{ +// +//} +// +//void NotifyQt::preDisplayMessages() +//{ +// +//} +// +//void NotifyQt::preDisplayChannels() +//{ +// +//} +// +//void NotifyQt::preDisplayTransfers() +//{ +// +// +//} diff --git a/retroshare-gui/src/rsiface/notifyqt.h b/retroshare-gui/src/rsiface/notifyqt.h index 80244082a..47b13cb2a 100644 --- a/retroshare-gui/src/rsiface/notifyqt.h +++ b/retroshare-gui/src/rsiface/notifyqt.h @@ -26,29 +26,30 @@ class NotifyQt: public QObject, public NotifyBase { Q_OBJECT public: - NotifyQt() : cDialog(NULL), pDialog(NULL), - dDialog(NULL), tDialog(NULL), - hDialog(NULL), mDialog(NULL), - sDialog(NULL), mWindow(NULL) - { return; } + NotifyQt() {} +// : cDialog(NULL), pDialog(NULL), +// dDialog(NULL), tDialog(NULL), +// hDialog(NULL), mDialog(NULL), +// sDialog(NULL), mWindow(NULL) +// { return; } virtual ~NotifyQt() { return; } - void setNetworkDialog(NetworkDialog *c) { cDialog = c; } - void setPeersDialog(PeersDialog *p) { pDialog = p; } - void setDirDialog(SharedFilesDialog *d) { dDialog = d; } - void setTransfersDialog(TransfersDialog *t) { tDialog = t; } - void setChatDialog(ChatDialog *m) { hDialog = m; } - void setMessagesDialog(MessagesDialog *m) { mDialog = m; } - void setChannelsDialog(ChannelsDialog *s) { sDialog = s; } - void setMessengerWindow(MessengerWindow *mw) { mWindow = mw; } - - void setRsIface(RsIface *i) { iface = i; } +// void setNetworkDialog(NetworkDialog *c) { cDialog = c; } +// void setPeersDialog(PeersDialog *p) { pDialog = p; } +// void setDirDialog(SharedFilesDialog *d) { dDialog = d; } +// void setTransfersDialog(TransfersDialog *t) { tDialog = t; } +// void setChatDialog(ChatDialog *m) { hDialog = m; } +// void setMessagesDialog(MessagesDialog *m) { mDialog = m; } +// void setChannelsDialog(ChannelsDialog *s) { sDialog = s; } +// void setMessengerWindow(MessengerWindow *mw) { mWindow = mw; } +// void setRsIface(RsIface *i) { iface = i; } virtual void notifyListPreChange(int list, int type); virtual void notifyListChange(int list, int type); virtual void notifyErrorMsg(int list, int sev, std::string msg); - virtual void notifyChat(); +// virtual void notifyChat(); + virtual void notifyChatStatus(const std::string& peer_id,const std::string& status_string); virtual void notifyHashingInfo(std::string fileinfo); #ifdef TURTLE_HOPPING virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list& found_files); @@ -66,6 +67,7 @@ class NotifyQt: public QObject, public NotifyBase void neighborsChanged() const ; void messagesChanged() const ; void configChanged() const ; + void chatStatusChanged(const QString&,const QString&) const ; #ifdef TURTLE_HOPPING void gotTurtleSearchResult(qulonglong search_id,TurtleFileInfo file) const ; #endif @@ -76,34 +78,34 @@ class NotifyQt: public QObject, public NotifyBase private: - void displayNeighbours(); - void displayFriends(); +// void displayNeighbours(); +// void displayFriends(); // void displayDirectories(); - void displaySearch(); - void displayChat(); - void displayMessages(); - void displayChannels(); - void displayTransfers(); +// void displaySearch(); +// void displayChat(); +// void displayMessages(); +// void displayChannels(); +// void displayTransfers(); - void preDisplayNeighbours(); - void preDisplayFriends(); +// void preDisplayNeighbours(); +// void preDisplayFriends(); // void preDisplayDirectories(); - void preDisplaySearch(); - void preDisplayMessages(); - void preDisplayChannels(); - void preDisplayTransfers(); +// void preDisplaySearch(); +// void preDisplayMessages(); +// void preDisplayChannels(); +// void preDisplayTransfers(); /* so we can update windows */ - NetworkDialog *cDialog; - PeersDialog *pDialog; - SharedFilesDialog *dDialog; - TransfersDialog *tDialog; - ChatDialog *hDialog; - MessagesDialog *mDialog; - ChannelsDialog *sDialog; - MessengerWindow *mWindow; +// NetworkDialog *cDialog; +// PeersDialog *pDialog; +// SharedFilesDialog *dDialog; +// TransfersDialog *tDialog; +// ChatDialog *hDialog; +// MessagesDialog *mDialog; +// ChannelsDialog *sDialog; +// MessengerWindow *mWindow; - RsIface *iface; +// RsIface *iface; }; #endif diff --git a/retroshare-gui/src/rsiface/rsiface.h b/retroshare-gui/src/rsiface/rsiface.h index 6d7bc69f9..1dc8326bb 100644 --- a/retroshare-gui/src/rsiface/rsiface.h +++ b/retroshare-gui/src/rsiface/rsiface.h @@ -200,6 +200,7 @@ class NotifyBase virtual void notifyListChange(int list, int type) { (void) list; (void) type; return; } virtual void notifyErrorMsg(int list, int sev, std::string msg) { (void) list; (void) sev; (void) msg; return; } virtual void notifyChat() { return; } + virtual void notifyChatStatus(const std::string& peer_id,const std::string& status_string) {} virtual void notifyHashingInfo(std::string fileinfo) { (void)fileinfo; return ; } virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list& files) { (void)files; } }; diff --git a/retroshare-gui/src/rsiface/rsmsgs.h b/retroshare-gui/src/rsiface/rsmsgs.h index bc6c2e2d6..f83a7b647 100644 --- a/retroshare-gui/src/rsiface/rsmsgs.h +++ b/retroshare-gui/src/rsiface/rsmsgs.h @@ -131,6 +131,7 @@ virtual bool MessageRead(std::string mid) = 0; virtual bool chatAvailable() = 0; virtual bool ChatSend(ChatInfo &ci) = 0; virtual bool getNewChat(std::list &chats) = 0; +virtual void sendStatusString(const std::string& id,const std::string& status_string) = 0 ; // get avatar data for peer pid virtual void getAvatarData(std::string pid,unsigned char *& data,int& size) = 0 ;