Added "peer is typing" functionality to private chat. This shoudld be extended to additional stuff like "idle", and to public chat. Also the display is the status bar of the chat window could be made nicer, e.g. directly in the msg window. Suppressed ChatDialog class that is not more used

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@1164 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2009-05-05 13:18:53 +00:00
parent ce3db07a63
commit e144e75ba6
18 changed files with 495 additions and 975 deletions

View File

@ -200,6 +200,7 @@ class NotifyBase
virtual void notifyListChange(int list, int type) { (void) list; (void) type; return; } 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 notifyErrorMsg(int list, int sev, std::string msg) { (void) list; (void) sev; (void) msg; return; }
virtual void notifyChat() { 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 notifyHashingInfo(std::string fileinfo) { (void)fileinfo; return ; }
virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list<TurtleFileInfo>& files) { (void)files; } virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list<TurtleFileInfo>& files) { (void)files; }
}; };

View File

@ -131,6 +131,7 @@ virtual bool MessageRead(std::string mid) = 0;
virtual bool chatAvailable() = 0; virtual bool chatAvailable() = 0;
virtual bool ChatSend(ChatInfo &ci) = 0; virtual bool ChatSend(ChatInfo &ci) = 0;
virtual bool getNewChat(std::list<ChatInfo> &chats) = 0; virtual bool getNewChat(std::list<ChatInfo> &chats) = 0;
virtual void sendStatusString(const std::string& id,const std::string& status_string) = 0 ;
// get avatar data for peer pid // get avatar data for peer pid
virtual void getAvatarData(std::string pid,unsigned char *& data,int& size) = 0 ; virtual void getAvatarData(std::string pid,unsigned char *& data,int& size) = 0 ;

View File

@ -109,6 +109,11 @@ bool p3Msgs::ChatSend(ChatInfo &ci)
return true; return true;
} }
void p3Msgs::sendStatusString(const std::string& peer_id,const std::string& status_string)
{
mChatSrv->sendStatusString(peer_id,status_string);
}
bool p3Msgs::chatAvailable() bool p3Msgs::chatAvailable()
{ {
return mChatSrv->receivedItems(); return mChatSrv->receivedItems();
@ -119,13 +124,13 @@ bool p3Msgs::getNewChat(std::list<ChatInfo> &chats)
/* get any messages and push them to iface */ /* get any messages and push them to iface */
// get the items from the list. // get the items from the list.
std::list<RsChatItem *> clist = mChatSrv -> getChatQueue(); std::list<RsChatMsgItem *> clist = mChatSrv -> getChatQueue();
if (clist.size() < 1) if (clist.size() < 1)
{ {
return false; return false;
} }
std::list<RsChatItem *>::iterator it; std::list<RsChatMsgItem *>::iterator it;
for(it = clist.begin(); it != clist.end(); it++) for(it = clist.begin(); it != clist.end(); it++)
{ {
ChatInfo ci; ChatInfo ci;
@ -142,7 +147,7 @@ bool p3Msgs::getNewChat(std::list<ChatInfo> &chats)
* for intAddChannel / intAddChannelMsg. * for intAddChannel / intAddChannelMsg.
*/ */
void p3Msgs::initRsChatInfo(RsChatItem *c, ChatInfo &i) void p3Msgs::initRsChatInfo(RsChatMsgItem *c, ChatInfo &i)
{ {
i.rsid = c -> PeerId(); i.rsid = c -> PeerId();
i.name = mAuthMgr->getName(i.rsid); i.name = mAuthMgr->getName(i.rsid);

View File

@ -32,7 +32,7 @@ class p3AuthMgr;
class p3MsgService; class p3MsgService;
class p3ChatService; class p3ChatService;
class RsChatItem; class RsChatMsgItem;
class p3Msgs: public RsMsgs class p3Msgs: public RsMsgs
{ {
@ -62,13 +62,14 @@ class p3Msgs: public RsMsgs
virtual bool chatAvailable(); virtual bool chatAvailable();
virtual bool ChatSend(ChatInfo &ci); virtual bool ChatSend(ChatInfo &ci);
virtual bool getNewChat(std::list<ChatInfo> &chats); virtual bool getNewChat(std::list<ChatInfo> &chats);
virtual void sendStatusString(const std::string& peer_id,const std::string& status_string) ;
/****************************************/ /****************************************/
private: private:
void initRsChatInfo(RsChatItem *c, ChatInfo &i); void initRsChatInfo(RsChatMsgItem *c, ChatInfo &i);
p3AuthMgr *mAuthMgr; p3AuthMgr *mAuthMgr;
p3MsgService *mMsgSrv; p3MsgService *mMsgSrv;

View File

@ -24,6 +24,7 @@
* *
*/ */
#include <stdexcept>
#include "serialiser/rsbaseserial.h" #include "serialiser/rsbaseserial.h"
#include "serialiser/rsmsgitems.h" #include "serialiser/rsmsgitems.h"
#include "serialiser/rstlvbase.h" #include "serialiser/rstlvbase.h"
@ -36,21 +37,9 @@
/*************************************************************************/ /*************************************************************************/
RsChatItem::~RsChatItem() std::ostream& RsChatMsgItem::print(std::ostream &out, uint16_t indent)
{ {
return; printRsItemBase(out, "RsChatMsgItem", indent);
}
void RsChatItem::clear()
{
chatFlags = 0;
sendTime = 0;
message.clear();
}
std::ostream &RsChatItem::print(std::ostream &out, uint16_t indent)
{
printRsItemBase(out, "RsChatItem", indent);
uint16_t int_Indent = indent + 2; uint16_t int_Indent = indent + 2;
printIndent(out, int_Indent); printIndent(out, int_Indent);
out << "QblogMs " << chatFlags << std::endl; out << "QblogMs " << chatFlags << std::endl;
@ -63,37 +52,103 @@ std::ostream &RsChatItem::print(std::ostream &out, uint16_t indent)
std::string cnv_message(message.begin(), message.end()); std::string cnv_message(message.begin(), message.end());
out << "msg: " << cnv_message << std::endl; out << "msg: " << cnv_message << std::endl;
printRsItemEnd(out, "RsChatItem", indent); printRsItemEnd(out, "RsChatMsgItem", indent);
return out; 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 */ uint32_t s = 8; /* header */
s += 4; /* chatFlags */ s += 4; /* chatFlags */
s += 4; /* sendTime */ 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; return s;
} }
/* serialise the data to the buffer */ /* 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; uint32_t offset = 0;
if (*pktsize < tlvsize) if (pktsize < tlvsize)
return false; /* not enough space */ return false; /* not enough space */
*pktsize = tlvsize; pktsize = tlvsize;
bool ok = true; 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() Header: " << ok << std::endl;
std::cerr << "RsChatSerialiser::serialiseItem() Size: " << tlvsize << std::endl; std::cerr << "RsChatSerialiser::serialiseItem() Size: " << tlvsize << std::endl;
#endif #endif
@ -102,94 +157,104 @@ bool RsChatSerialiser::serialiseItem(RsChatItem *item, void *data, uint32_t
offset += 8; offset += 8;
/* add mandatory parts first */ /* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, item->chatFlags); ok &= setRawUInt32(data, tlvsize, &offset, chatFlags);
ok &= setRawUInt32(data, tlvsize, &offset, item->sendTime); ok &= setRawUInt32(data, tlvsize, &offset, sendTime);
ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_MSG, item->message); ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_MSG, message);
if (offset != tlvsize) if (offset != tlvsize)
{ {
ok = false; ok = false;
#ifdef RSSERIAL_DEBUG #ifdef CHAT_DEBUG
std::cerr << "RsChatSerialiser::serialiseItem() Size Error! " << std::endl; std::cerr << "RsChatSerialiser::serialiseItem() Size Error! " << std::endl;
#endif #endif
} }
#ifdef RSSERIAL_DEBUG #ifdef CHAT_DEBUG
std::cerr << "computed size: " << 256*((unsigned char*)data)[6]+((unsigned char*)data)[7] << std::endl ; std::cerr << "computed size: " << 256*((unsigned char*)data)[6]+((unsigned char*)data)[7] << std::endl ;
#endif #endif
return ok; 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 tlvsize = serial_size() ;
uint32_t rstype = getRsItemId(data);
uint32_t rssize = getRsItemSize(data);
uint32_t offset = 0; uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || pktsize = tlvsize;
(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;
bool ok = true; bool ok = true;
/* ready to load */ ok &= setRsItemHeader(data, tlvsize, PacketId(), tlvsize);
RsChatItem *item = new RsChatItem();
item->clear(); #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 */ /* skip the header */
offset += 8; 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 */ /* get mandatory parts first */
ok &= getRawUInt32(data, rssize, &offset, &(item->chatFlags)); ok &= getRawUInt32(data, rssize, &offset, &chatFlags);
ok &= getRawUInt32(data, rssize, &offset, &(item->sendTime)); ok &= getRawUInt32(data, rssize, &offset, &sendTime);
ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_MSG, item->message); 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) if (offset != rssize)
{ throw std::runtime_error("Size error while deserializing.") ;
/* error */
delete item;
return NULL;
}
if (!ok) if (!ok)
{ throw std::runtime_error("Unknown error while deserializing.") ;
delete item;
return NULL;
} }
return item;
}
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);
}
/*************************************************************************/ /*************************************************************************/

View File

@ -40,46 +40,73 @@ const uint32_t RS_CHAT_FLAG_REQUESTS_AVATAR = 0x0002;
const uint32_t RS_CHAT_FLAG_CONTAINS_AVATAR = 0x0004; const uint32_t RS_CHAT_FLAG_CONTAINS_AVATAR = 0x0004;
const uint32_t RS_CHAT_FLAG_AVATAR_AVAILABLE = 0x0008; 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 class RsChatItem: public RsItem
{ {
public: public:
RsChatItem() RsChatItem(uint8_t chat_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_CHAT,chat_subtype) {}
:RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_CHAT,
RS_PKT_SUBTYPE_DEFAULT) virtual ~RsChatItem() {}
{ return; } virtual void clear() {}
virtual ~RsChatItem(); virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) = 0 ;
virtual void clear();
std::ostream &print(std::ostream &out, uint16_t indent = 0); 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
};
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 chatFlags;
uint32_t sendTime; uint32_t sendTime;
std::wstring message; std::wstring message;
/* not serialised */ /* not serialised */
uint32_t recvTime; 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 class RsChatSerialiser: public RsSerialType
{ {
public: public:
RsChatSerialiser() RsChatSerialiser() :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_CHAT) {}
:RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_CHAT)
{ return; }
virtual ~RsChatSerialiser()
{ return; }
virtual uint32_t size(RsItem *); virtual uint32_t size (RsItem *item)
virtual bool serialise (RsItem *item, void *data, uint32_t *size); {
return static_cast<RsChatItem *>(item)->serial_size() ;
}
virtual bool serialise(RsItem *item, void *data, uint32_t *size)
{
return static_cast<RsChatItem *>(item)->serialise(data,*size) ;
}
virtual RsItem *deserialise (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);
}; };
/**************************************************************************/ /**************************************************************************/

View File

@ -24,6 +24,7 @@
*/ */
#include "util/rsdir.h" #include "util/rsdir.h"
#include "rsiface/rsiface.h"
#include "pqi/pqibin.h" #include "pqi/pqibin.h"
#include "pqi/pqinotify.h" #include "pqi/pqinotify.h"
#include "pqi/pqiarchive.h" #include "pqi/pqiarchive.h"
@ -90,7 +91,7 @@ int p3ChatService::sendChat(std::wstring msg)
for(it = ids.begin(); it != ids.end(); it++) for(it = ids.begin(); it != ids.end(); it++)
{ {
RsChatItem *ci = new RsChatItem(); RsChatMsgItem *ci = new RsChatMsgItem();
ci->PeerId(*it); ci->PeerId(*it);
ci->chatFlags = 0; ci->chatFlags = 0;
@ -170,6 +171,20 @@ class p3ChatService::AvatarInfo
}; };
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) int p3ChatService::sendPrivateChat( std::wstring msg, std::string id)
{ {
// make chat item.... // make chat item....
@ -178,7 +193,7 @@ int p3ChatService::sendPrivateChat(std::wstring msg, std::string id)
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
RsChatItem *ci = new RsChatItem(); RsChatMsgItem *ci = new RsChatMsgItem();
ci->PeerId(id); ci->PeerId(id);
ci->chatFlags = RS_CHAT_FLAG_PRIVATE; ci->chatFlags = RS_CHAT_FLAG_PRIVATE;
@ -215,14 +230,21 @@ int p3ChatService::sendPrivateChat(std::wstring msg, std::string id)
return 1; return 1;
} }
std::list<RsChatItem *> p3ChatService::getChatQueue() std::list<RsChatMsgItem *> p3ChatService::getChatQueue()
{ {
time_t now = time(NULL); time_t now = time(NULL);
RsChatItem *ci = NULL; RsItem *item ;
std::list<RsChatItem *> ilist; std::list<RsChatMsgItem *> ilist;
while(NULL != (ci = (RsChatItem *) recvItem())) while(NULL != (item=recvItem()))
{
#ifdef CHAT_DEBUG
std::cerr << "p3ChatService::getChatQueue() Item:" << (void*)item << std::endl ;
#endif
RsChatMsgItem *ci = dynamic_cast<RsChatMsgItem*>(item) ;
if(ci != NULL)
{ {
#ifdef CHAT_DEBUG #ifdef CHAT_DEBUG
std::cerr << "p3ChatService::getChatQueue() Item:"; std::cerr << "p3ChatService::getChatQueue() Item:";
@ -261,6 +283,19 @@ std::list<RsChatItem *> p3ChatService::getChatQueue()
ilist.push_back(ci); ilist.push_back(ci);
} }
} }
RsChatStatusItem *cs = dynamic_cast<RsChatStatusItem*>(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 ;
}
}
return ilist; return ilist;
} }
@ -284,7 +319,7 @@ void p3ChatService::setOwnAvatarJpegData(const unsigned char *data,int size)
IndicateConfigChanged(); IndicateConfigChanged();
} }
void p3ChatService::receiveAvatarJpegData(RsChatItem *ci) void p3ChatService::receiveAvatarJpegData(RsChatMsgItem *ci)
{ {
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
std::cerr << "p3chatservice: received avatar jpeg data for peer " << ci->PeerId() << ". Storing it." << std::endl ; 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. // Doesn't have avatar. Request it.
// //
RsChatItem *ci = new RsChatItem(); RsChatMsgItem *ci = new RsChatMsgItem();
ci->PeerId(peer_id); ci->PeerId(peer_id);
ci->chatFlags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_REQUESTS_AVATAR ; 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); sendItem(ci);
} }
RsChatItem *p3ChatService::makeOwnAvatarItem() RsChatMsgItem *p3ChatService::makeOwnAvatarItem()
{ {
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ 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->chatFlags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_CONTAINS_AVATAR ;
ci->sendTime = time(NULL); ci->sendTime = time(NULL);
@ -371,7 +406,7 @@ void p3ChatService::sendAvatarJpegData(const std::string& peer_id)
if(_own_avatar != NULL) if(_own_avatar != NULL)
{ {
RsChatItem *ci = makeOwnAvatarItem(); RsChatMsgItem *ci = makeOwnAvatarItem();
ci->PeerId(peer_id); ci->PeerId(peer_id);
// take avatar, and embed it into a std::wstring. // 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); BinFileInterface *in = new BinFileInterface(msgfile.c_str(), BIN_FLAGS_READABLE | BIN_FLAGS_HASH_DATA);
pqiarchive *pa_in = new pqiarchive(rss, in, BIN_FLAGS_READABLE); pqiarchive *pa_in = new pqiarchive(rss, in, BIN_FLAGS_READABLE);
RsItem *item; RsItem *item;
RsChatItem *mitem; RsChatMsgItem *mitem;
while((item = pa_in -> GetItem())) while((item = pa_in -> GetItem()))
{ {
if(NULL != (mitem = dynamic_cast<RsChatItem *>(item))) if(NULL != (mitem = dynamic_cast<RsChatMsgItem *>(item)))
{ {
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
@ -451,7 +486,7 @@ bool p3ChatService::saveConfiguration()
if(_own_avatar != NULL) if(_own_avatar != NULL)
{ {
std::cerr << "Saving avatar config to file " << msgfile << std::endl ; std::cerr << "Saving avatar config to file " << msgfile << std::endl ;
RsChatItem *ci = makeOwnAvatarItem() ; RsChatMsgItem *ci = makeOwnAvatarItem() ;
ci->PeerId(mConnMgr->getOwnId()); ci->PeerId(mConnMgr->getOwnId());
if(!pa_out -> SendItem(ci)) if(!pa_out -> SendItem(ci))

View File

@ -50,6 +50,7 @@ class p3ChatService: public p3Service, public pqiConfig
int sendChat(std::wstring msg); int sendChat(std::wstring msg);
int sendPrivateChat(std::wstring msg, std::string id); 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 /// 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 /// 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 setOwnAvatarJpegData(const unsigned char *data,int size) ;
void getOwnAvatarJpegData(unsigned char *& data,int& size) ; void getOwnAvatarJpegData(unsigned char *& data,int& size) ;
std::list<RsChatItem *> getChatQueue(); std::list<RsChatMsgItem *> getChatQueue();
/*** Overloaded from pqiConfig ****/ /*** Overloaded from pqiConfig ****/
virtual bool loadConfiguration(std::string &loadHash); virtual bool loadConfiguration(std::string &loadHash);
@ -76,12 +77,12 @@ class p3ChatService: public p3Service, public pqiConfig
void sendAvatarJpegData(const std::string& peer_id) ; void sendAvatarJpegData(const std::string& peer_id) ;
/// Receive the avatar in a chat item, with RS_CHAT_RECEIVE_AVATAR flag. /// 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 /// Sends a request for an avatar to the peer of given id
void sendAvatarRequest(const std::string& peer_id) ; void sendAvatarRequest(const std::string& peer_id) ;
RsChatItem *makeOwnAvatarItem() ; RsChatMsgItem *makeOwnAvatarItem() ;
p3ConnectMgr *mConnMgr; p3ConnectMgr *mConnMgr;

View File

@ -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 <QtGui>
#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 <sstream>
#include <QTextCodec>
#include <QTextEdit>
#include <QTextCursor>
#include <QTextList>
#include <QTextStream>
#include <QTextDocumentFragment>
#include <QContextMenuEvent>
#include <QMenu>
#include <QCursor>
#include <QPoint>
#include <QMouseEvent>
#include <QPixmap>
#include <QHeaderView>
#include <QtGui/QKeyEvent>
/** 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<ChatInfo> newchat;
if (!rsMsgs->getNewChat(newchat))
{
return;
}
QTextEdit *msgWidget = ui.msgText;
std::list<ChatInfo>::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 = "<span style=\"color:#C00000\">" + timestamp + "</span>" +
"<span style=\"color:#2D84C9\"><strong>" + " " + name + "</strong></span>";
extraTxt += line;
extraTxt += QString::fromStdWString(it->msg);
/* add it everytime */
currenttxt += extraTxt;
QHashIterator<QString, QString> i(smileys);
while(i.hasNext())
{
i.next();
currenttxt.replace(i.key(), "<img src=\"" + i.value() + "\">");
}
msgWidget->setHtml(currenttxt);
QScrollBar *qsb = msgWidget->verticalScrollBar();
qsb -> setValue(qsb->maximum());
}
}
void ChatDialog::checkChat()
{
/* if <return> 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 <return> 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 <return> 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<std::string> peers;
std::list<std::string>::iterator it;
if (!rsPeers)
{
/* not ready yet! */
return;
}
rsPeers->getOnlineList(peers);
/* get a link to the table */
QTreeWidget *sendWidget = ui.msgSendList;
QList<QTreeWidgetItem *> 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<std::string, PopupChatDialog *>::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("<font color='grey'>")+ QTime::currentTime().toString(QString::fromUtf8("hh:mm:ss")) + QString::fromUtf8("</font> - <font color='") + color.name() +QString::fromUtf8("'><i>") + info + QString::fromUtf8("</i></font>"));
}
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<QString, QString> 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<QPushButton*>(sender())->toolTip());
}

View File

@ -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<QString, QString> smileys;
std::map<std::string, PopupChatDialog *> chatDialogs;
QFont mCurrentFont; /* how the text will come out */
/** Qt Designer generated object */
Ui::ChatDialog ui;
};
#endif

View File

@ -50,7 +50,7 @@ public:
void clearOldChats(); void clearOldChats();
void loadEmoticonsgroupchat(); void loadEmoticonsgroupchat();
void setChatDialog(ChatDialog *cd); // void setChatDialog(ChatDialog *cd);
public slots: public slots:
@ -72,6 +72,8 @@ private slots:
/** Create the context popup menu and it's submenus */ /** Create the context popup menu and it's submenus */
void peertreeWidgetCostumPopupMenu( QPoint point ); void peertreeWidgetCostumPopupMenu( QPoint point );
void updatePeerStatusString(const QString& peer_id,const QString& chat_status) ;
/** Export friend in Friends Dialog */ /** Export friend in Friends Dialog */
void exportfriend(); void exportfriend();
/** Remove friend */ /** Remove friend */
@ -109,7 +111,7 @@ private:
/* (2) Utility Fns */ /* (2) Utility Fns */
QTreeWidgetItem *getCurrentPeer(); QTreeWidgetItem *getCurrentPeer();
ChatDialog *chatDialog; // ChatDialog *chatDialog;
/** Define the popup menus for the Context menu */ /** Define the popup menus for the Context menu */

View File

@ -63,6 +63,7 @@ PopupChatDialog::PopupChatDialog(std::string id, std::string name,
loadEmoticons(); loadEmoticons();
last_status_send_time = 0 ;
styleHtm = appDir + "/style/chat/default.htm"; styleHtm = appDir + "/style/chat/default.htm";
/* Hide Avatar frame */ /* Hide Avatar frame */
@ -85,9 +86,8 @@ PopupChatDialog::PopupChatDialog(std::string id, std::string name,
connect(ui.styleButton, SIGNAL(clicked()), SLOT(changeStyle())); connect(ui.styleButton, SIGNAL(clicked()), SLOT(changeStyle()));
// Create the status bar // Create the status bar
std::ostringstream statusstr; resetStatusBar() ;
statusstr << "Chatting with " << dialogName << " (" << id << ")" ;
statusBar()->showMessage(QString::fromStdString(statusstr.str()));
ui.textBrowser->setOpenExternalLinks ( false ); ui.textBrowser->setOpenExternalLinks ( false );
QString title = QString::fromStdString(name) + " :" + tr(" RetroShare - Encrypted Chat") ; QString title = QString::fromStdString(name) + " :" + tr(" RetroShare - Encrypted Chat") ;
@ -129,6 +129,30 @@ PopupChatDialog::PopupChatDialog(std::string id, std::string name,
updatePeerAvatar(id) ; 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. */ /** Destructor. */
PopupChatDialog::~PopupChatDialog() PopupChatDialog::~PopupChatDialog()
{ {
@ -261,21 +285,10 @@ void PopupChatDialog::checkChat()
/* if <return> at the end of the text -> we can send it! */ /* if <return> at the end of the text -> we can send it! */
QTextEdit *chatWidget = ui.chattextEdit; QTextEdit *chatWidget = ui.chattextEdit;
std::string txt = chatWidget->toPlainText().toStdString(); std::string txt = chatWidget->toPlainText().toStdString();
if ('\n' == txt[txt.length()-1]) if ('\n' == txt[txt.length()-1] && txt.length()-1 == txt.find('\n')) /* only if on first line! */
{
//std::cerr << "Found <return> 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(); sendChat();
}
}
else else
{ updateStatusTyping() ;
//std::cerr << "No <return> found in :" << txt << ":";
//std::cerr << std::endl;
}
} }

View File

@ -75,6 +75,9 @@ public slots:
void changeStyle(); void changeStyle();
void resetStatusBar() ;
void updateStatusTyping() ;
void updateStatusString(const QString&) ;
protected: protected:
void closeEvent (QCloseEvent * event); void closeEvent (QCloseEvent * event);
@ -107,6 +110,7 @@ private:
unsigned int lastChatTime; unsigned int lastChatTime;
std::string lastChatName; std::string lastChatName;
time_t last_status_send_time ;
QHash<QString, QString> smileys; QHash<QString, QString> smileys;
QColor mCurrentColor; QColor mCurrentColor;
QFont mCurrentFont; QFont mCurrentFont;

View File

@ -122,7 +122,6 @@ int main(int argc, char *argv[])
RsIface *iface = createRsIface(*notify); RsIface *iface = createRsIface(*notify);
RsControl *rsServer = createRsControl(*iface, *notify); RsControl *rsServer = createRsControl(*iface, *notify);
notify->setRsIface(iface);
/* save to the global variables */ /* save to the global variables */
rsiface = iface; rsiface = iface;
@ -140,14 +139,17 @@ int main(int argc, char *argv[])
//skinWindow->setCentralWidget(w); //skinWindow->setCentralWidget(w);
/* Attach the Dialogs, to the Notify Class */ /* Attach the Dialogs, to the Notify Class */
notify->setNetworkDialog(w->networkDialog); // Not needed anymore since the notify class is directly connected by Qt signals/slots to the correct widgets below.
notify->setPeersDialog(w->peersDialog); //
notify->setDirDialog(w->sharedfilesDialog); // notify->setRsIface(iface);
notify->setTransfersDialog(w->transfersDialog); // notify->setNetworkDialog(w->networkDialog);
notify->setChatDialog(w->chatDialog); // notify->setPeersDialog(w->peersDialog);
notify->setMessagesDialog(w->messagesDialog); // notify->setDirDialog(w->sharedfilesDialog);
notify->setChannelsDialog(w->channelsDialog); // notify->setTransfersDialog(w->transfersDialog);
notify->setMessengerWindow(w->messengerWindow); // 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 // 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. // 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(messagesChanged()) ,w->messagesDialog ,SLOT(insertMessages() )) ;
QObject::connect(notify,SIGNAL(configChanged()) ,w->messagesDialog ,SLOT(displayConfig() )) ; 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 */ /* only show window, if not startMinimized */
if (!startMinimised) if (!startMinimised)
{ {

View File

@ -39,16 +39,19 @@ void NotifyQt::notifyErrorMsg(int list, int type, std::string msg)
return; 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 #ifdef TURTLE_HOPPING
void NotifyQt::notifyTurtleSearchResult(uint32_t search_id,const std::list<TurtleFileInfo>& files) void NotifyQt::notifyTurtleSearchResult(uint32_t search_id,const std::list<TurtleFileInfo>& files)
{ {
std::cerr << "in notify search result..." << std::endl ; std::cerr << "in notify search result..." << std::endl ;
// QList<TurtleFileInfo> qfiles ;
for(std::list<TurtleFileInfo>::const_iterator it(files.begin());it!=files.end();++it) for(std::list<TurtleFileInfo>::const_iterator it(files.begin());it!=files.end();++it)
emit gotTurtleSearchResult(search_id,*it) ; emit gotTurtleSearchResult(search_id,*it) ;
// qfiles.push_back(*it) ;
} }
#endif #endif
void NotifyQt::notifyHashingInfo(std::string fileinfo) void NotifyQt::notifyHashingInfo(std::string fileinfo)
@ -56,10 +59,11 @@ void NotifyQt::notifyHashingInfo(std::string fileinfo)
emit hashingInfoChanged(QString::fromStdString(fileinfo)) ; emit hashingInfoChanged(QString::fromStdString(fileinfo)) ;
} }
void NotifyQt::notifyChat() //void NotifyQt::notifyChat()
{ //{
return; // std::cerr << "Received chat notification" << std::endl ;
} // return;
//}
void NotifyQt::notifyListChange(int list, int type) void NotifyQt::notifyListChange(int list, int type)
{ {
@ -90,7 +94,6 @@ void NotifyQt::notifyListChange(int list, int type)
emit filesPostModChanged(true) ; /* Local */ emit filesPostModChanged(true) ; /* Local */
break; break;
case NOTIFY_LIST_SEARCHLIST: case NOTIFY_LIST_SEARCHLIST:
//displaySearch();
break; break;
case NOTIFY_LIST_MESSAGELIST: case NOTIFY_LIST_MESSAGELIST:
#ifdef DEBUG #ifdef DEBUG
@ -99,7 +102,6 @@ void NotifyQt::notifyListChange(int list, int type)
emit messagesChanged() ; emit messagesChanged() ;
break; break;
case NOTIFY_LIST_CHANNELLIST: case NOTIFY_LIST_CHANNELLIST:
//displayChannels();
break; break;
case NOTIFY_LIST_TRANSFERLIST: case NOTIFY_LIST_TRANSFERLIST:
#ifdef DEBUG #ifdef DEBUG
@ -128,7 +130,6 @@ void NotifyQt::notifyListPreChange(int list, int type)
switch(list) switch(list)
{ {
case NOTIFY_LIST_NEIGHBOURS: case NOTIFY_LIST_NEIGHBOURS:
//preDisplayNeighbours();
break; break;
case NOTIFY_LIST_FRIENDS: case NOTIFY_LIST_FRIENDS:
emit friendsChanged() ; emit friendsChanged() ;
@ -138,16 +139,12 @@ void NotifyQt::notifyListPreChange(int list, int type)
emit filesPreModChanged(true) ; /* local */ emit filesPreModChanged(true) ; /* local */
break; break;
case NOTIFY_LIST_SEARCHLIST: case NOTIFY_LIST_SEARCHLIST:
//preDisplaySearch();
break; break;
case NOTIFY_LIST_MESSAGELIST: case NOTIFY_LIST_MESSAGELIST:
//preDisplayMessages();
break; break;
case NOTIFY_LIST_CHANNELLIST: case NOTIFY_LIST_CHANNELLIST:
//preDisplayChannels();
break; break;
case NOTIFY_LIST_TRANSFERLIST: case NOTIFY_LIST_TRANSFERLIST:
//preDisplayTransfers();
break; break;
default: default:
break; 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. if (time(NULL) > lastTs + 5) // update every 5 seconds. I don't know what to do with these.
{ {
displayChannels(); // displayChannels();
} }
lastTs = time(NULL) ; lastTs = time(NULL) ;
@ -273,88 +270,88 @@ void NotifyQt::UpdateGUI()
} }
} }
void NotifyQt::displaySearch() //void NotifyQt::displaySearch()
{ //{
iface->lockData(); /* Lock Interface */ // iface->lockData(); /* Lock Interface */
//
//#ifdef NOTIFY_DEBUG
// std::ostringstream out;
// std::cerr << out.str();
//#endif
//
// iface->unlockData(); /* UnLock Interface */
//}
#ifdef NOTIFY_DEBUG // void NotifyQt::displayChat()
std::ostringstream out; // {
std::cerr << out.str(); // iface->lockData(); /* Lock Interface */
#endif //
// #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::preDisplaySearch()
} //{
//
void NotifyQt::displayChat() //}
{ //
iface->lockData(); /* Lock Interface */ //void NotifyQt::preDisplayMessages()
//{
#ifdef NOTIFY_DEBUG //
std::ostringstream out; //}
std::cerr << out.str(); //
#endif //void NotifyQt::preDisplayChannels()
//{
iface->unlockData(); /* UnLock Interface */ //
//}
if (hDialog) //
hDialog -> insertChat(); //void NotifyQt::preDisplayTransfers()
} //{
//
//
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()
{
}

View File

@ -26,29 +26,30 @@ class NotifyQt: public QObject, public NotifyBase
{ {
Q_OBJECT Q_OBJECT
public: public:
NotifyQt() : cDialog(NULL), pDialog(NULL), NotifyQt() {}
dDialog(NULL), tDialog(NULL), // : cDialog(NULL), pDialog(NULL),
hDialog(NULL), mDialog(NULL), // dDialog(NULL), tDialog(NULL),
sDialog(NULL), mWindow(NULL) // hDialog(NULL), mDialog(NULL),
{ return; } // sDialog(NULL), mWindow(NULL)
// { return; }
virtual ~NotifyQt() { return; } virtual ~NotifyQt() { return; }
void setNetworkDialog(NetworkDialog *c) { cDialog = c; } // void setNetworkDialog(NetworkDialog *c) { cDialog = c; }
void setPeersDialog(PeersDialog *p) { pDialog = p; } // void setPeersDialog(PeersDialog *p) { pDialog = p; }
void setDirDialog(SharedFilesDialog *d) { dDialog = d; } // void setDirDialog(SharedFilesDialog *d) { dDialog = d; }
void setTransfersDialog(TransfersDialog *t) { tDialog = t; } // void setTransfersDialog(TransfersDialog *t) { tDialog = t; }
void setChatDialog(ChatDialog *m) { hDialog = m; } // void setChatDialog(ChatDialog *m) { hDialog = m; }
void setMessagesDialog(MessagesDialog *m) { mDialog = m; } // void setMessagesDialog(MessagesDialog *m) { mDialog = m; }
void setChannelsDialog(ChannelsDialog *s) { sDialog = s; } // void setChannelsDialog(ChannelsDialog *s) { sDialog = s; }
void setMessengerWindow(MessengerWindow *mw) { mWindow = mw; } // void setMessengerWindow(MessengerWindow *mw) { mWindow = mw; }
// void setRsIface(RsIface *i) { iface = i; }
void setRsIface(RsIface *i) { iface = i; }
virtual void notifyListPreChange(int list, int type); virtual void notifyListPreChange(int list, int type);
virtual void notifyListChange(int list, int type); virtual void notifyListChange(int list, int type);
virtual void notifyErrorMsg(int list, int sev, std::string msg); 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); virtual void notifyHashingInfo(std::string fileinfo);
#ifdef TURTLE_HOPPING #ifdef TURTLE_HOPPING
virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list<TurtleFileInfo>& found_files); virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list<TurtleFileInfo>& found_files);
@ -66,6 +67,7 @@ class NotifyQt: public QObject, public NotifyBase
void neighborsChanged() const ; void neighborsChanged() const ;
void messagesChanged() const ; void messagesChanged() const ;
void configChanged() const ; void configChanged() const ;
void chatStatusChanged(const QString&,const QString&) const ;
#ifdef TURTLE_HOPPING #ifdef TURTLE_HOPPING
void gotTurtleSearchResult(qulonglong search_id,TurtleFileInfo file) const ; void gotTurtleSearchResult(qulonglong search_id,TurtleFileInfo file) const ;
#endif #endif
@ -76,34 +78,34 @@ class NotifyQt: public QObject, public NotifyBase
private: private:
void displayNeighbours(); // void displayNeighbours();
void displayFriends(); // void displayFriends();
// void displayDirectories(); // void displayDirectories();
void displaySearch(); // void displaySearch();
void displayChat(); // void displayChat();
void displayMessages(); // void displayMessages();
void displayChannels(); // void displayChannels();
void displayTransfers(); // void displayTransfers();
void preDisplayNeighbours(); // void preDisplayNeighbours();
void preDisplayFriends(); // void preDisplayFriends();
// void preDisplayDirectories(); // void preDisplayDirectories();
void preDisplaySearch(); // void preDisplaySearch();
void preDisplayMessages(); // void preDisplayMessages();
void preDisplayChannels(); // void preDisplayChannels();
void preDisplayTransfers(); // void preDisplayTransfers();
/* so we can update windows */ /* so we can update windows */
NetworkDialog *cDialog; // NetworkDialog *cDialog;
PeersDialog *pDialog; // PeersDialog *pDialog;
SharedFilesDialog *dDialog; // SharedFilesDialog *dDialog;
TransfersDialog *tDialog; // TransfersDialog *tDialog;
ChatDialog *hDialog; // ChatDialog *hDialog;
MessagesDialog *mDialog; // MessagesDialog *mDialog;
ChannelsDialog *sDialog; // ChannelsDialog *sDialog;
MessengerWindow *mWindow; // MessengerWindow *mWindow;
RsIface *iface; // RsIface *iface;
}; };
#endif #endif

View File

@ -200,6 +200,7 @@ class NotifyBase
virtual void notifyListChange(int list, int type) { (void) list; (void) type; return; } 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 notifyErrorMsg(int list, int sev, std::string msg) { (void) list; (void) sev; (void) msg; return; }
virtual void notifyChat() { 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 notifyHashingInfo(std::string fileinfo) { (void)fileinfo; return ; }
virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list<TurtleFileInfo>& files) { (void)files; } virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list<TurtleFileInfo>& files) { (void)files; }
}; };

View File

@ -131,6 +131,7 @@ virtual bool MessageRead(std::string mid) = 0;
virtual bool chatAvailable() = 0; virtual bool chatAvailable() = 0;
virtual bool ChatSend(ChatInfo &ci) = 0; virtual bool ChatSend(ChatInfo &ci) = 0;
virtual bool getNewChat(std::list<ChatInfo> &chats) = 0; virtual bool getNewChat(std::list<ChatInfo> &chats) = 0;
virtual void sendStatusString(const std::string& id,const std::string& status_string) = 0 ;
// get avatar data for peer pid // get avatar data for peer pid
virtual void getAvatarData(std::string pid,unsigned char *& data,int& size) = 0 ; virtual void getAvatarData(std::string pid,unsigned char *& data,int& size) = 0 ;