Merge branch 'master' into webui

This commit is contained in:
zeners 2016-01-24 17:59:19 +01:00
commit 640345c490
76 changed files with 817 additions and 531 deletions

View File

@ -1,5 +1,46 @@
retroshare06 (0.6.0-1.XXXXXX~YYYYYY) YYYYYY; urgency=low retroshare06 (0.6.0-1.XXXXXX~YYYYYY) YYYYYY; urgency=low
f13c81b csoler Sat, 23 Jan 2016 13:17:12 -0500 Merge pull request #258 from PhenomRetroShare/Fix_QuoteLinesWithImage
9b64b96 csoler Sat, 23 Jan 2016 13:03:29 -0500 fixed potential crash in pqisslstore
1d2be23 Phenom Sat, 23 Jan 2016 18:17:49 +0100 Fix Quote Lines With Image
70bf938 defnax Sat, 23 Jan 2016 13:37:08 +0100 reduced the default width & height reorder in MessagePage, move Distant Message box to the top.
fc0067f csoler Fri, 22 Jan 2016 22:06:31 -0500 fixed bug in network graph search sizes
c428739 csoler Fri, 22 Jan 2016 21:32:35 -0500 cleaned the network graph a little bit. Removed text, updated bounding boxes, removed background
b362544 csoler Fri, 22 Jan 2016 09:31:40 -0500 fixed compilation
b3df4c1 csoler Thu, 21 Jan 2016 23:55:22 -0500 made the Global router stats widget more efficient/compact/explicit
449aba9 csoler Thu, 21 Jan 2016 22:44:48 -0500 fixed compilation of SearchDialog.cpp
94b5868 csoler Thu, 21 Jan 2016 21:49:52 -0500 moved SearchDialog into FileTransfer/
6a32da2 csoler Thu, 21 Jan 2016 21:40:48 -0500 removed explicit size constraint on listview for config page (screws up the view in HDPI screens
55d0a21 csoler Thu, 21 Jan 2016 21:19:40 -0500 added cache of latest GXS tunnel data items for the last 10 minutes in order to avoid replays of
9347b86 csoler Thu, 21 Jan 2016 11:48:41 -0500 new simple solution for sound on linux based on using system sound player. To be tested.
9999742 csoler Thu, 21 Jan 2016 11:32:17 -0500 reverted commit for phonon since phonon is deprecated. Will be replaced by qtmultimedia in
7488ba1 csoler Wed, 20 Jan 2016 23:56:22 -0500 removed feedback from messages to mGrpServerUpdateTS, which is now only updated when the subscri
c473200 csoler Wed, 20 Jan 2016 23:34:25 -0500 moved getCurrentTS() inside RTT packet sending loop (suggestion from Jo)
e25787b csoler Wed, 20 Jan 2016 23:25:08 -0500 fixed sound on linux using phonon. This should be extensible to all unix systems
fc3606c csoler Wed, 20 Jan 2016 14:02:13 -0500 fixed DHT icon size problem
9063612 csoler Wed, 20 Jan 2016 11:19:36 -0500 fixed utf8 issue in ChatWidget. To be tested.
c597c8c csoler Tue, 19 Jan 2016 23:19:46 -0500 removed explicit spacing sizes in plugins page
3203249 csoler Tue, 19 Jan 2016 22:59:11 -0500 fixed size of help icons in MainPage class
597f541 csoler Tue, 19 Jan 2016 22:44:27 -0500 added 2 icons
3d58f9b csoler Tue, 19 Jan 2016 22:35:58 -0500 added correct icons in ToasterStatus
b382c3e csoler Tue, 19 Jan 2016 22:16:25 -0500 fixed icon sizes in peerstatus/statusbar
a2d8cc8 csoler Tue, 19 Jan 2016 22:01:26 -0500 fixed DHT status icon sizes and added tooltip
37204d7 csoler Tue, 19 Jan 2016 21:46:22 -0500 fixed icon in NewsFeed, added missing spacer in IdDialog
49c1d56 csoler Tue, 19 Jan 2016 21:45:55 -0500 increased GXS post size limit to just below 200K
1471979 csoler Tue, 19 Jan 2016 18:08:47 -0500 added a few tooltips in Tor configuration panel
43ee506 csoler Tue, 19 Jan 2016 10:13:24 -0500 added automatic GXS message rejection when item size exceeds 200K. Should fix the forums that go
dedd6d4 csoler Mon, 18 Jan 2016 23:53:54 -0500 disabled debug info
68a0395 csoler Mon, 18 Jan 2016 23:53:06 -0500 fixed a few bugs in existing msg fragmentation code. Signature checking still not working, not N
2b52456 defnax Mon, 18 Jan 2016 13:36:38 +0100 Added new iconset for Voip, by Beluga
39e6a9b csoler Sat, 16 Jan 2016 20:44:52 -0500 fixed up People context menu so as to handle actions for multiple persons at once
1edfcf9 csoler Sat, 16 Jan 2016 13:41:24 -0500 do not time stamp banned GXS ids
8296fa9 csoler Sat, 16 Jan 2016 11:30:15 -0500 added checkbox to toggle logscale in statistics
63b88ec defnax Sat, 16 Jan 2016 14:50:12 +0100 correct sorting for "Reputation" in People, patch by Eugene Tooms
-- Cyril Soler <csoler@users.sourceforge.net> Sat, 23 Jan 2016 16:00:00 +0100
retroshare06 (0.6.0-1.20160115.a34f66aa~trusty) trusty; urgency=low
0ff6349 thunder2 Fri, 15 Jan 2016 12:01:37 +0100 Fixed possibility of XXE injection in FeedReader plugin. 0ff6349 thunder2 Fri, 15 Jan 2016 12:01:37 +0100 Fixed possibility of XXE injection in FeedReader plugin.
748147f thunder2 Fri, 15 Jan 2016 12:00:02 +0100 Fixed Windows compile. 748147f thunder2 Fri, 15 Jan 2016 12:00:02 +0100 Fixed Windows compile.
b5f6059 Cyril Soler Fri, 15 Jan 2016 10:07:21 -0500 deprecated updateClientSyncTS() which is not needed anymore b5f6059 Cyril Soler Fri, 15 Jan 2016 10:07:21 -0500 deprecated updateClientSyncTS() which is not needed anymore

View File

@ -216,6 +216,7 @@
//#define NXS_NET_DEBUG_6 1 //#define NXS_NET_DEBUG_6 1
#define GIXS_CUT_OFF 0 #define GIXS_CUT_OFF 0
//#define NXS_FRAG
// The constant below have a direct influence on how fast forums/channels/posted/identity groups propagate and on the overloading of queues: // The constant below have a direct influence on how fast forums/channels/posted/identity groups propagate and on the overloading of queues:
// //
@ -232,6 +233,7 @@
#define REJECTED_MESSAGE_RETRY_DELAY 24*3600 // re-try rejected messages every 24hrs. Most of the time this is because the peer's reputation has changed. #define REJECTED_MESSAGE_RETRY_DELAY 24*3600 // re-try rejected messages every 24hrs. Most of the time this is because the peer's reputation has changed.
#define GROUP_STATS_UPDATE_DELAY 1800 // update unsubscribed group statistics every 30 mins #define GROUP_STATS_UPDATE_DELAY 1800 // update unsubscribed group statistics every 30 mins
#define GROUP_STATS_UPDATE_NB_PEERS 2 // update unsubscribed group statistics every 30 mins #define GROUP_STATS_UPDATE_NB_PEERS 2 // update unsubscribed group statistics every 30 mins
#define MAX_ALLOWED_GXS_MESSAGE_SIZE 199000 // 200,000 bytes including signature and headers
// Debug system to allow to print only for some IDs (group, Peer, etc) // Debug system to allow to print only for some IDs (group, Peer, etc)
@ -239,7 +241,7 @@
static const RsPeerId peer_to_print = RsPeerId(std::string("")) ; static const RsPeerId peer_to_print = RsPeerId(std::string("")) ;
static const RsGxsGroupId group_id_to_print = RsGxsGroupId(std::string("" )) ; // use this to allow to this group id only, or "" for all IDs static const RsGxsGroupId group_id_to_print = RsGxsGroupId(std::string("" )) ; // use this to allow to this group id only, or "" for all IDs
static const uint32_t service_to_print = 0 ; // use this to allow to this service id only, or 0 for all services static const uint32_t service_to_print = 0x215 ; // use this to allow to this service id only, or 0 for all services
// warning. Numbers should be SERVICE IDS (see serialiser/rsserviceids.h. E.g. 0x0215 for forums) // warning. Numbers should be SERVICE IDS (see serialiser/rsserviceids.h. E.g. 0x0215 for forums)
class nullstream: public std::ostream {}; class nullstream: public std::ostream {};
@ -889,7 +891,13 @@ void RsGxsNetService::subscribeStatusChanged(const RsGxsGroupId& grpId,bool subs
else else
it->second->msgUpdateTS = 0 ; // reset! it->second->msgUpdateTS = 0 ; // reset!
// no need to update mGrpServerUpdateItem since the ::updateServerSyncTS() call will do it. // We also update mGrpServerUpdateItem so as to trigger a new grp list exchange with friends (friends will send their known ClientTS which
// will be lower than our own grpUpdateTS, triggering our sending of the new subscribed grp list.
if(mGrpServerUpdateItem == NULL)
mGrpServerUpdateItem = new RsGxsServerGrpUpdateItem(mServType);
mGrpServerUpdateItem->grpUpdateTS = time(NULL) ;
} }
bool RsGxsNetService::fragmentMsg(RsNxsMsg& msg, MsgFragments& msgFragments) const bool RsGxsNetService::fragmentMsg(RsNxsMsg& msg, MsgFragments& msgFragments) const
@ -898,7 +906,8 @@ bool RsGxsNetService::fragmentMsg(RsNxsMsg& msg, MsgFragments& msgFragments) con
uint32_t msgSize = msg.msg.TlvSize(); uint32_t msgSize = msg.msg.TlvSize();
uint32_t dataLeft = msgSize; uint32_t dataLeft = msgSize;
uint8_t nFragments = ceil(float(msgSize)/FRAGMENT_SIZE); uint8_t nFragments = ceil(float(msgSize)/FRAGMENT_SIZE);
char buffer[FRAGMENT_SIZE];
RsTemporaryMemory buffer(FRAGMENT_SIZE);
int currPos = 0; int currPos = 0;
@ -964,11 +973,26 @@ RsNxsMsg* RsGxsNetService::deFragmentMsg(MsgFragments& msgFragments) const
if(msgFragments.size() == 1) if(msgFragments.size() == 1)
{ {
RsNxsMsg* m = msgFragments.front(); RsNxsMsg* m = msgFragments.front();
if(m->count > 1)
if(m->count > 1) // normally mcount should be exactly 1, but if not initialised (old versions) it's going to be 0
{
// delete everything
std::cerr << "(WW) Cannot deFragment message set. m->count=" << m->count << ", but msgFragments.size()=" << msgFragments.size() << ". Incomplete? Dropping all." << std::endl;
for(uint32_t i=0;i<msgFragments.size();++i)
delete msgFragments[i] ;
msgFragments.clear();
return NULL; return NULL;
}
else else
{
// single piece. No need to say anything. Just return it.
msgFragments.clear();
return m; return m;
} }
}
// first determine total size for binary data // first determine total size for binary data
MsgFragments::iterator mit = msgFragments.begin(); MsgFragments::iterator mit = msgFragments.begin();
@ -977,9 +1001,21 @@ RsNxsMsg* RsGxsNetService::deFragmentMsg(MsgFragments& msgFragments) const
for(; mit != msgFragments.end(); ++mit) for(; mit != msgFragments.end(); ++mit)
datSize += (*mit)->msg.bin_len; datSize += (*mit)->msg.bin_len;
char* data = new char[datSize]; RsTemporaryMemory data(datSize) ;
if(!data)
{
for(uint32_t i=0;i<msgFragments.size();++i)
delete msgFragments[i] ;
msgFragments.clear();
return NULL ;
}
uint32_t currPos = 0; uint32_t currPos = 0;
std::cerr << "(II) deFragmenting long message of size " << datSize << ", from " << msgFragments.size() << " pieces." << std::endl;
for(mit = msgFragments.begin(); mit != msgFragments.end(); ++mit) for(mit = msgFragments.begin(); mit != msgFragments.end(); ++mit)
{ {
RsNxsMsg* msg = *mit; RsNxsMsg* msg = *mit;
@ -995,10 +1031,17 @@ RsNxsMsg* RsGxsNetService::deFragmentMsg(MsgFragments& msgFragments) const
msg->transactionNumber = m.transactionNumber; msg->transactionNumber = m.transactionNumber;
msg->meta = m.meta; msg->meta = m.meta;
delete[] data; // now clean!
for(uint32_t i=0;i<msgFragments.size();++i)
delete msgFragments[i] ;
msgFragments.clear();
return msg; return msg;
} }
// This is unused apparently, since groups are never large. Anyway, we keep it in case we need it.
RsNxsGrp* RsGxsNetService::deFragmentGrp(GrpFragments& grpFragments) const RsNxsGrp* RsGxsNetService::deFragmentGrp(GrpFragments& grpFragments) const
{ {
if(grpFragments.empty()) return NULL; if(grpFragments.empty()) return NULL;
@ -1257,7 +1300,7 @@ struct MsgFragCollate
bool operator()(RsNxsMsg* msg) { return msg->msgId == mMsgId;} bool operator()(RsNxsMsg* msg) { return msg->msgId == mMsgId;}
}; };
void RsGxsNetService::collateMsgFragments(MsgFragments fragments, std::map<RsGxsMessageId, MsgFragments>& partFragments) const void RsGxsNetService::collateMsgFragments(MsgFragments& fragments, std::map<RsGxsMessageId, MsgFragments>& partFragments) const
{ {
// get all unique message Ids; // get all unique message Ids;
MsgFragments::iterator vit = fragments.begin(); MsgFragments::iterator vit = fragments.begin();
@ -1779,6 +1822,10 @@ void RsGxsNetService::updateServerSyncTS()
// retrieve all grps and update TS // retrieve all grps and update TS
mDataStore->retrieveGxsGrpMetaData(gxsMap); mDataStore->retrieveGxsGrpMetaData(gxsMap);
#ifdef TO_REMOVE
// (cyril) This code is removed because it is inconsistent: the list of grps does not need to be updated when
// new posts arrive. The two (grp list and msg list) are handled independently.
// as a grp list server also note this is the latest item you have // as a grp list server also note this is the latest item you have
if(mGrpServerUpdateItem == NULL) if(mGrpServerUpdateItem == NULL)
mGrpServerUpdateItem = new RsGxsServerGrpUpdateItem(mServType); mGrpServerUpdateItem = new RsGxsServerGrpUpdateItem(mServType);
@ -1787,6 +1834,7 @@ void RsGxsNetService::updateServerSyncTS()
// we have unsubscribed a group. // we have unsubscribed a group.
mGrpServerUpdateItem->grpUpdateTS = 0 ; mGrpServerUpdateItem->grpUpdateTS = 0 ;
#endif
bool change = false; bool change = false;
// then remove from mServerMsgUpdateMap, all items that are not in the group list! // then remove from mServerMsgUpdateMap, all items that are not in the group list!
@ -1824,6 +1872,7 @@ void RsGxsNetService::updateServerSyncTS()
ServerMsgMap::iterator mapIT = mServerMsgUpdateMap.find(grpId); ServerMsgMap::iterator mapIT = mServerMsgUpdateMap.find(grpId);
RsGxsServerMsgUpdateItem* msui = NULL; RsGxsServerMsgUpdateItem* msui = NULL;
#ifdef TO_REMOVE
// That accounts for modification of the meta data. // That accounts for modification of the meta data.
if(mGrpServerUpdateItem->grpUpdateTS < grpMeta->mPublishTs) if(mGrpServerUpdateItem->grpUpdateTS < grpMeta->mPublishTs)
@ -1833,6 +1882,7 @@ void RsGxsNetService::updateServerSyncTS()
#endif #endif
mGrpServerUpdateItem->grpUpdateTS = grpMeta->mPublishTs; mGrpServerUpdateItem->grpUpdateTS = grpMeta->mPublishTs;
} }
#endif
if(mapIT == mServerMsgUpdateMap.end()) if(mapIT == mServerMsgUpdateMap.end())
{ {
@ -1856,6 +1906,7 @@ void RsGxsNetService::updateServerSyncTS()
#endif #endif
} }
#ifdef TO_REMOVE
// This might be very inefficient with time. This is needed because an old message might have been received, so the last modification time // This might be very inefficient with time. This is needed because an old message might have been received, so the last modification time
// needs to account for this so that a friend who hasn't // needs to account for this so that a friend who hasn't
@ -1867,6 +1918,7 @@ void RsGxsNetService::updateServerSyncTS()
mGrpServerUpdateItem->grpUpdateTS = grpMeta->mRecvTS; mGrpServerUpdateItem->grpUpdateTS = grpMeta->mRecvTS;
change = true; change = true;
} }
#endif
} }
// actual change in config settings, then save configuration // actual change in config settings, then save configuration
@ -2289,13 +2341,15 @@ void RsGxsNetService::locked_processCompletedIncomingTrans(NxsTransaction* tr)
std::cerr << "RsGxsNetService::processCompletedTransactions(): item did not caste to msg" << std::endl; std::cerr << "RsGxsNetService::processCompletedTransactions(): item did not caste to msg" << std::endl;
} }
#ifdef NSXS_FRAG #ifdef NXS_FRAG
std::map<RsGxsGroupId, MsgFragments > collatedMsgs; // (cyril) This code does not work. Since we do not really need message fragmenting, I won't fix it.
collateMsgFragments(msgs, collatedMsgs);
std::map<RsGxsMessageId, MsgFragments > collatedMsgs;
collateMsgFragments(msgs, collatedMsgs); // this destroys msgs whatsoever and recovers memory when needed
msgs.clear(); msgs.clear();
std::map<RsGxsGroupId, MsgFragments >::iterator mit = collatedMsgs.begin(); std::map<RsGxsMessageId, MsgFragments >::iterator mit = collatedMsgs.begin();
for(; mit != collatedMsgs.end(); ++mit) for(; mit != collatedMsgs.end(); ++mit)
{ {
MsgFragments& f = mit->second; MsgFragments& f = mit->second;
@ -2304,6 +2358,7 @@ void RsGxsNetService::locked_processCompletedIncomingTrans(NxsTransaction* tr)
if(msg) if(msg)
msgs.push_back(msg); msgs.push_back(msg);
} }
collatedMsgs.clear();
#endif #endif
#ifdef NXS_NET_DEBUG_0 #ifdef NXS_NET_DEBUG_0
GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " ...and notifying observer of " << msgs.size() << " new messages." << std::endl; GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " ...and notifying observer of " << msgs.size() << " new messages." << std::endl;
@ -3175,13 +3230,20 @@ void RsGxsNetService::locked_genSendMsgsTransaction(NxsTransaction* tr)
msg->PeerId(peerId); msg->PeerId(peerId);
msg->transactionNumber = transN; msg->transactionNumber = transN;
#ifndef NXS_FRAG // Quick trick to clamp messages with an exceptionnally large size. Signature will fail on client side, and the message
newTr->mItems.push_back(msg); // will be rejected.
msgSize++;
#else if(msg->msg.bin_len > MAX_ALLOWED_GXS_MESSAGE_SIZE)
{
std::cerr << "(WW) message with ID " << msg->msgId << " in group " << msg->grpId << " exceeds size limit of " << MAX_ALLOWED_GXS_MESSAGE_SIZE << " bytes. Actual size is " << msg->msg.bin_len << " bytes. Message will be truncated and rejected at client." << std::endl;
msg->msg.bin_len = 1 ; // arbitrary small size, but not 0. No need to send the data since it's going to be rejected.
}
#ifdef NXS_FRAG
MsgFragments fragments; MsgFragments fragments;
fragmentMsg(*msg, fragments); fragmentMsg(*msg, fragments);
delete msg ;
MsgFragments::iterator mit = fragments.begin(); MsgFragments::iterator mit = fragments.begin();
for(; mit != fragments.end(); ++mit) for(; mit != fragments.end(); ++mit)
@ -3189,7 +3251,14 @@ void RsGxsNetService::locked_genSendMsgsTransaction(NxsTransaction* tr)
newTr->mItems.push_back(*mit); newTr->mItems.push_back(*mit);
msgSize++; msgSize++;
} }
#else
msg->count = 1; // only one piece. This is to keep compatibility if we ever implement fragmenting in the future.
msg->pos = 0;
newTr->mItems.push_back(msg);
msgSize++;
#endif #endif
} }
} }

View File

@ -435,7 +435,7 @@ private:
* @param fragments message fragments which are not necessarily from the same message * @param fragments message fragments which are not necessarily from the same message
* @param partFragments the partitioned fragments (into message ids) * @param partFragments the partitioned fragments (into message ids)
*/ */
void collateMsgFragments(MsgFragments fragments, std::map<RsGxsMessageId, MsgFragments>& partFragments) const; void collateMsgFragments(MsgFragments &fragments, std::map<RsGxsMessageId, MsgFragments>& partFragments) const;
/*! /*!
* Note that if all fragments for a group are not found then its fragments are dropped * Note that if all fragments for a group are not found then its fragments are dropped

View File

@ -28,6 +28,7 @@
#include "rsgxsutil.h" #include "rsgxsutil.h"
#include "retroshare/rsgxsflags.h" #include "retroshare/rsgxsflags.h"
#include "retroshare/rspeers.h" #include "retroshare/rspeers.h"
#include "retroshare/rsreputations.h"
#include "pqi/pqihash.h" #include "pqi/pqihash.h"
#include "gxs/rsgixs.h" #include "gxs/rsgixs.h"
@ -161,6 +162,7 @@ bool RsGxsIntegrityCheck::check()
std::cerr << "TimeStamping group authors' key ID " << grp->metaData->mAuthorId << " in group ID " << grp->grpId << std::endl; std::cerr << "TimeStamping group authors' key ID " << grp->metaData->mAuthorId << " in group ID " << grp->grpId << std::endl;
#endif #endif
if(rsReputations!=NULL && !rsReputations->isIdentityBanned(grp->metaData->mAuthorId))
used_gxs_ids.insert(grp->metaData->mAuthorId) ; used_gxs_ids.insert(grp->metaData->mAuthorId) ;
} }
} }
@ -242,6 +244,7 @@ bool RsGxsIntegrityCheck::check()
#ifdef GXSUTIL_DEBUG #ifdef GXSUTIL_DEBUG
std::cerr << "TimeStamping message authors' key ID " << msg->metaData->mAuthorId << " in message " << msg->msgId << ", group ID " << msg->grpId<< std::endl; std::cerr << "TimeStamping message authors' key ID " << msg->metaData->mAuthorId << " in message " << msg->msgId << ", group ID " << msg->grpId<< std::endl;
#endif #endif
if(rsReputations!=NULL && !rsReputations->isIdentityBanned(msg->metaData->mAuthorId))
used_gxs_ids.insert(msg->metaData->mAuthorId) ; used_gxs_ids.insert(msg->metaData->mAuthorId) ;
} }

View File

@ -54,6 +54,7 @@ static const uint32_t RS_GXS_TUNNEL_DH_STATUS_HALF_KEY_DONE = 0x0001 ;
static const uint32_t RS_GXS_TUNNEL_DH_STATUS_KEY_AVAILABLE = 0x0002 ; static const uint32_t RS_GXS_TUNNEL_DH_STATUS_KEY_AVAILABLE = 0x0002 ;
static const uint32_t RS_GXS_TUNNEL_DELAY_BETWEEN_RESEND = 10 ; // re-send every 10 secs. static const uint32_t RS_GXS_TUNNEL_DELAY_BETWEEN_RESEND = 10 ; // re-send every 10 secs.
static const uint32_t RS_GXS_TUNNEL_DATA_PRINT_STORAGE_DELAY = 600 ; // store old message ids for 10 minutes.
static const uint32_t GXS_TUNNEL_ENCRYPTION_HMAC_SIZE = SHA_DIGEST_LENGTH ; static const uint32_t GXS_TUNNEL_ENCRYPTION_HMAC_SIZE = SHA_DIGEST_LENGTH ;
static const uint32_t GXS_TUNNEL_ENCRYPTION_IV_SIZE = 8 ; static const uint32_t GXS_TUNNEL_ENCRYPTION_IV_SIZE = 8 ;
@ -73,9 +74,6 @@ p3GxsTunnelService::p3GxsTunnelService(RsGixs *pids)
: mGixs(pids), mGxsTunnelMtx("GXS tunnel") : mGixs(pids), mGxsTunnelMtx("GXS tunnel")
{ {
mTurtle = NULL ; mTurtle = NULL ;
// any value is fine here, even 0, since items in different RS sessions will use different AES keys.
global_item_counter = 0;//RSRandom::random_u64() ;
} }
void p3GxsTunnelService::connectToTurtleRouter(p3turtle *tr) void p3GxsTunnelService::connectToTurtleRouter(p3turtle *tr)
@ -196,7 +194,9 @@ void p3GxsTunnelService::flush()
for(std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::iterator it(_gxs_tunnel_contacts.begin());it!=_gxs_tunnel_contacts.end();) for(std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::iterator it(_gxs_tunnel_contacts.begin());it!=_gxs_tunnel_contacts.end();)
{ {
// Remove any tunnel that was remotely closed, since we cannot use it anymore. // All sorts of cleaning. We start with the ones that may remove stuff, for efficiency reasons.
// 1 - Remove any tunnel that was remotely closed, since we cannot use it anymore.
if(it->second.status == RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED && it->second.last_contact + 20 < now) if(it->second.status == RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED && it->second.last_contact + 20 < now)
{ {
@ -207,6 +207,8 @@ void p3GxsTunnelService::flush()
continue ; continue ;
} }
// 2 - re-digg tunnels that have died out of inaction
if(it->second.last_contact+20+GXS_TUNNEL_KEEP_ALIVE_TIMEOUT < now && it->second.status == RS_GXS_TUNNEL_STATUS_CAN_TALK) if(it->second.last_contact+20+GXS_TUNNEL_KEEP_ALIVE_TIMEOUT < now && it->second.status == RS_GXS_TUNNEL_STATUS_CAN_TALK)
{ {
#ifdef DEBUG_GXS_TUNNEL #ifdef DEBUG_GXS_TUNNEL
@ -228,6 +230,9 @@ void p3GxsTunnelService::flush()
mTurtle->forceReDiggTunnels( randomHashFromDestinationGxsId(it->second.to_gxs_id) ); mTurtle->forceReDiggTunnels( randomHashFromDestinationGxsId(it->second.to_gxs_id) );
} }
} }
// send keep alive packets to active tunnels.
if(it->second.last_keep_alive_sent + GXS_TUNNEL_KEEP_ALIVE_TIMEOUT < now && it->second.status == RS_GXS_TUNNEL_STATUS_CAN_TALK) if(it->second.last_keep_alive_sent + GXS_TUNNEL_KEEP_ALIVE_TIMEOUT < now && it->second.status == RS_GXS_TUNNEL_STATUS_CAN_TALK)
{ {
RsGxsTunnelStatusItem *cs = new RsGxsTunnelStatusItem ; RsGxsTunnelStatusItem *cs = new RsGxsTunnelStatusItem ;
@ -244,6 +249,23 @@ void p3GxsTunnelService::flush()
std::cerr << "(II) GxsTunnelService:: Sending keep alive packet to gxs id " << it->first << std::endl; std::cerr << "(II) GxsTunnelService:: Sending keep alive packet to gxs id " << it->first << std::endl;
#endif #endif
} }
// clean old received data prints.
for(std::map<uint64_t,time_t>::iterator it2=it->second.received_data_prints.begin();it2!=it->second.received_data_prints.end();)
if(now > it2->second + RS_GXS_TUNNEL_DATA_PRINT_STORAGE_DELAY)
{
#ifdef DEBUG_GXS_TUNNEL
std::cerr << "(II) erasing old data print for message #" << it2->first << " in tunnel " << it->first << std::endl;
#endif
std::map<uint64_t,time_t>::iterator tmp(it2) ;
++tmp ;
it->second.received_data_prints.erase(it2) ;
it2 = tmp ;
}
else
++it2 ;
++it ; ++it ;
} }
} }
@ -347,6 +369,16 @@ void p3GxsTunnelService::handleRecvTunnelDataItem(const RsGxsTunnelId& tunnel_id
it2->second.client_services.insert(item->service_id) ; it2->second.client_services.insert(item->service_id) ;
peer_from = it2->second.to_gxs_id ; peer_from = it2->second.to_gxs_id ;
} }
// Check if the item has already been received. This is necessary because we actually re-send items until an ACK is received. If the ACK gets lost (connection interrupted) the
// item may be received twice. This is conservative and ensure that no item is lost nor received twice.
if(it2->second.received_data_prints.find(item->unique_item_counter) != it2->second.received_data_prints.end())
{
std::cerr << "(WW) received the same data item #" << std::hex << item->unique_item_counter << std::dec << " twice in last 20 mins. Tunnel id=" << tunnel_id << ". Probably a replay. Item will be dropped." << std::endl;
return ;
}
it2->second.received_data_prints[item->unique_item_counter] = time(NULL) ;
} }
if(service->acceptDataFromPeer(peer_from,tunnel_id)) if(service->acceptDataFromPeer(peer_from,tunnel_id))
@ -1325,7 +1357,7 @@ bool p3GxsTunnelService::sendData(const RsGxsTunnelId &tunnel_id, uint32_t servi
RsGxsTunnelDataItem *item = new RsGxsTunnelDataItem ; RsGxsTunnelDataItem *item = new RsGxsTunnelDataItem ;
item->unique_item_counter = global_item_counter++; // this allows to make the item unique item->unique_item_counter = RSRandom::random_u64(); // this allows to make the item unique, except very rarely, we we don't care.
item->flags = 0; // not used yet. item->flags = 0; // not used yet.
item->service_id = service_id; item->service_id = service_id;
item->data_size = size; // encrypted data size item->data_size = size; // encrypted data size

View File

@ -171,6 +171,7 @@ private:
RsTurtleGenericTunnelItem::Direction direction ; // specifiec wether we are client(managing the tunnel) or server. RsTurtleGenericTunnelItem::Direction direction ; // specifiec wether we are client(managing the tunnel) or server.
TurtleFileHash hash ; // hash that is last used. This is necessary for handling tunnel establishment TurtleFileHash hash ; // hash that is last used. This is necessary for handling tunnel establishment
std::set<uint32_t> client_services ;// services that used this tunnel std::set<uint32_t> client_services ;// services that used this tunnel
std::map<uint64_t,time_t> received_data_prints ; // list of recently received messages, to avoid duplicates. Kept for 20 mins at most.
uint32_t total_sent ; uint32_t total_sent ;
uint32_t total_received ; uint32_t total_received ;
}; };
@ -252,8 +253,6 @@ private:
RsGixs *mGixs ; RsGixs *mGixs ;
RsMutex mGxsTunnelMtx ; RsMutex mGxsTunnelMtx ;
uint64_t global_item_counter ;
std::map<uint32_t,RsGxsTunnelClientService*> mRegisteredServices ; std::map<uint32_t,RsGxsTunnelClientService*> mRegisteredServices ;
void debug_dump(); void debug_dump();

View File

@ -391,18 +391,19 @@ bool pqiSSLstore::encryptedSendItems(const std::list<RsItem*>& rsItemList)
std::list<RsItem*>::const_iterator it; std::list<RsItem*>::const_iterator it;
uint32_t sizeItems = 0, sizeItem = 0; uint32_t sizeItems = 0, sizeItem = 0;
uint32_t offset = 0; uint32_t offset = 0;
char* data = NULL;
for(it = rsItemList.begin(); it != rsItemList.end(); ++it) for(it = rsItemList.begin(); it != rsItemList.end(); ++it)
if(*it != NULL)
sizeItems += rsSerialiser->size(*it); sizeItems += rsSerialiser->size(*it);
data = new char[sizeItems]; RsTemporaryMemory data(sizeItems) ;
for(it = rsItemList.begin(); it != rsItemList.end(); ++it) for(it = rsItemList.begin(); it != rsItemList.end(); ++it)
if(*it != NULL)
{ {
sizeItem = rsSerialiser->size(*it); sizeItem = rsSerialiser->size(*it);
if(rsSerialiser->serialise(*it, (data+offset),&sizeItem)) if(rsSerialiser->serialise(*it, &data[offset],&sizeItem))
offset += sizeItem; offset += sizeItem;
else else
std::cerr << "(EE) pqiSSLstore::encryptedSendItems(): One item did not serialize. The item is probably unknown from the serializer. Dropping the item. " << std::endl; std::cerr << "(EE) pqiSSLstore::encryptedSendItems(): One item did not serialize. The item is probably unknown from the serializer. Dropping the item. " << std::endl;
@ -418,9 +419,6 @@ bool pqiSSLstore::encryptedSendItems(const std::list<RsItem*>& rsItemList)
else else
result = false; result = false;
if(data != NULL)
delete[] data;
return result; return result;
} }

View File

@ -190,8 +190,6 @@ void p3rtt::sendPingMeasurements()
mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, idList); mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, idList);
double ts = getCurrentTS();
#ifdef DEBUG_RTT #ifdef DEBUG_RTT
std::cerr << "p3rtt::sendPingMeasurements() @ts: " << ts; std::cerr << "p3rtt::sendPingMeasurements() @ts: " << ts;
std::cerr << std::endl; std::cerr << std::endl;
@ -205,6 +203,7 @@ void p3rtt::sendPingMeasurements()
std::cerr << "p3rtt::sendPingMeasurements() Pinging: " << *it; std::cerr << "p3rtt::sendPingMeasurements() Pinging: " << *it;
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
double ts = getCurrentTS();
/* create the packet */ /* create the packet */
RsRttPingItem *pingPkt = new RsRttPingItem(); RsRttPingItem *pingPkt = new RsRttPingItem();

View File

@ -53,11 +53,11 @@ VOIPChatWidgetHolder::VOIPChatWidgetHolder(ChatWidget *chatWidget, VOIPNotify *n
QSize buttonSize = QSize(iconSize + QSize(3,3)); QSize buttonSize = QSize(iconSize + QSize(3,3));
QIcon iconaudioListenToggleButton ; QIcon iconaudioListenToggleButton ;
iconaudioListenToggleButton.addPixmap(QPixmap(":/images/audio-volume-muted.png")) ; iconaudioListenToggleButton.addPixmap(QPixmap(":/images/speaker_mute.png")) ;
iconaudioListenToggleButton.addPixmap(QPixmap(":/images/audio-volume-high.png"),QIcon::Normal,QIcon::On) ; iconaudioListenToggleButton.addPixmap(QPixmap(":/images/speaker.png"),QIcon::Normal,QIcon::On) ;
iconaudioListenToggleButton.addPixmap(QPixmap(":/images/audio-volume-high.png"),QIcon::Disabled,QIcon::On) ; iconaudioListenToggleButton.addPixmap(QPixmap(":/images/speaker.png"),QIcon::Disabled,QIcon::On) ;
iconaudioListenToggleButton.addPixmap(QPixmap(":/images/audio-volume-high.png"),QIcon::Active,QIcon::On) ; iconaudioListenToggleButton.addPixmap(QPixmap(":/images/speaker.png"),QIcon::Active,QIcon::On) ;
iconaudioListenToggleButton.addPixmap(QPixmap(":/images/audio-volume-high.png"),QIcon::Selected,QIcon::On) ; iconaudioListenToggleButton.addPixmap(QPixmap(":/images/speaker.png"),QIcon::Selected,QIcon::On) ;
audioListenToggleButton = new QToolButton ; audioListenToggleButton = new QToolButton ;
audioListenToggleButton->setIcon(iconaudioListenToggleButton) ; audioListenToggleButton->setIcon(iconaudioListenToggleButton) ;
@ -71,11 +71,11 @@ VOIPChatWidgetHolder::VOIPChatWidgetHolder(ChatWidget *chatWidget, VOIPNotify *n
audioListenToggleButton->setEnabled(false); audioListenToggleButton->setEnabled(false);
QIcon iconaudioCaptureToggleButton ; QIcon iconaudioCaptureToggleButton ;
iconaudioCaptureToggleButton.addPixmap(QPixmap(":/images/call-start.png")) ; iconaudioCaptureToggleButton.addPixmap(QPixmap(":/images/phone.png")) ;
iconaudioCaptureToggleButton.addPixmap(QPixmap(":/images/call-hold.png"),QIcon::Normal,QIcon::On) ; iconaudioCaptureToggleButton.addPixmap(QPixmap(":/images/microphone_mute.png"),QIcon::Normal,QIcon::On) ;
iconaudioCaptureToggleButton.addPixmap(QPixmap(":/images/call-hold.png"),QIcon::Disabled,QIcon::On) ; iconaudioCaptureToggleButton.addPixmap(QPixmap(":/images/microphone_mute.png"),QIcon::Disabled,QIcon::On) ;
iconaudioCaptureToggleButton.addPixmap(QPixmap(":/images/call-hold.png"),QIcon::Active,QIcon::On) ; iconaudioCaptureToggleButton.addPixmap(QPixmap(":/images/microphone_mute.png"),QIcon::Active,QIcon::On) ;
iconaudioCaptureToggleButton.addPixmap(QPixmap(":/images/call-hold.png"),QIcon::Selected,QIcon::On) ; iconaudioCaptureToggleButton.addPixmap(QPixmap(":/images/microphone_mute.png"),QIcon::Selected,QIcon::On) ;
audioCaptureToggleButton = new QToolButton ; audioCaptureToggleButton = new QToolButton ;
audioCaptureToggleButton->setIcon(iconaudioCaptureToggleButton) ; audioCaptureToggleButton->setIcon(iconaudioCaptureToggleButton) ;
@ -88,11 +88,11 @@ VOIPChatWidgetHolder::VOIPChatWidgetHolder(ChatWidget *chatWidget, VOIPNotify *n
audioCaptureToggleButton->setToolTip(tr("Start Call")); audioCaptureToggleButton->setToolTip(tr("Start Call"));
QIcon iconvideoCaptureToggleButton ; QIcon iconvideoCaptureToggleButton ;
iconvideoCaptureToggleButton.addPixmap(QPixmap(":/images/video-icon-on.png")) ; iconvideoCaptureToggleButton.addPixmap(QPixmap(":/images/filmcam.png")) ;
iconvideoCaptureToggleButton.addPixmap(QPixmap(":/images/video-icon-off.png"),QIcon::Normal,QIcon::On) ; iconvideoCaptureToggleButton.addPixmap(QPixmap(":/images/filmcam-off.png"),QIcon::Normal,QIcon::On) ;
iconvideoCaptureToggleButton.addPixmap(QPixmap(":/images/video-icon-off.png"),QIcon::Disabled,QIcon::On) ; iconvideoCaptureToggleButton.addPixmap(QPixmap(":/images/filmcam-off.png"),QIcon::Disabled,QIcon::On) ;
iconvideoCaptureToggleButton.addPixmap(QPixmap(":/images/video-icon-off.png"),QIcon::Active,QIcon::On) ; iconvideoCaptureToggleButton.addPixmap(QPixmap(":/images/filmcam-off.png"),QIcon::Active,QIcon::On) ;
iconvideoCaptureToggleButton.addPixmap(QPixmap(":/images/video-icon-off.png"),QIcon::Selected,QIcon::On) ; iconvideoCaptureToggleButton.addPixmap(QPixmap(":/images/filmcam-off.png"),QIcon::Selected,QIcon::On) ;
videoCaptureToggleButton = new QToolButton ; videoCaptureToggleButton = new QToolButton ;
videoCaptureToggleButton->setIcon(iconvideoCaptureToggleButton) ; videoCaptureToggleButton->setIcon(iconvideoCaptureToggleButton) ;
@ -105,7 +105,7 @@ VOIPChatWidgetHolder::VOIPChatWidgetHolder(ChatWidget *chatWidget, VOIPNotify *n
videoCaptureToggleButton->setToolTip(tr("Start Video Call")); videoCaptureToggleButton->setToolTip(tr("Start Video Call"));
hangupButton = new QToolButton ; hangupButton = new QToolButton ;
hangupButton->setIcon(QIcon(":/images/call-stop.png")) ; hangupButton->setIcon(QIcon(":/images/phone_hangup.png")) ;
hangupButton->setIconSize(iconSize) ; hangupButton->setIconSize(iconSize) ;
hangupButton->setMinimumSize(buttonSize) ; hangupButton->setMinimumSize(buttonSize) ;
hangupButton->setMaximumSize(buttonSize) ; hangupButton->setMaximumSize(buttonSize) ;
@ -116,11 +116,11 @@ VOIPChatWidgetHolder::VOIPChatWidgetHolder(ChatWidget *chatWidget, VOIPNotify *n
hangupButton->hide(); hangupButton->hide();
QIcon iconhideChatTextToggleButton ; QIcon iconhideChatTextToggleButton ;
iconhideChatTextToggleButton.addPixmap(QPixmap(":/images/orange-bubble-64.png")) ; iconhideChatTextToggleButton.addPixmap(QPixmap(":/images/chat-bubble.png")) ;
iconhideChatTextToggleButton.addPixmap(QPixmap(":/images/white-bubble-64.png"),QIcon::Normal,QIcon::On) ; iconhideChatTextToggleButton.addPixmap(QPixmap(":/images/chat-bubble.png"),QIcon::Normal,QIcon::On) ;
iconhideChatTextToggleButton.addPixmap(QPixmap(":/images/white-bubble-64.png"),QIcon::Disabled,QIcon::On) ; iconhideChatTextToggleButton.addPixmap(QPixmap(":/images/chat-bubble.png"),QIcon::Disabled,QIcon::On) ;
iconhideChatTextToggleButton.addPixmap(QPixmap(":/images/white-bubble-64.png"),QIcon::Active,QIcon::On) ; iconhideChatTextToggleButton.addPixmap(QPixmap(":/images/chat-bubble.png"),QIcon::Active,QIcon::On) ;
iconhideChatTextToggleButton.addPixmap(QPixmap(":/images/white-bubble-64.png"),QIcon::Selected,QIcon::On) ; iconhideChatTextToggleButton.addPixmap(QPixmap(":/images/chat-bubble.png"),QIcon::Selected,QIcon::On) ;
hideChatTextToggleButton = new QToolButton ; hideChatTextToggleButton = new QToolButton ;
hideChatTextToggleButton->setIcon(iconhideChatTextToggleButton) ; hideChatTextToggleButton->setIcon(iconhideChatTextToggleButton) ;
@ -134,11 +134,11 @@ VOIPChatWidgetHolder::VOIPChatWidgetHolder(ChatWidget *chatWidget, VOIPNotify *n
hideChatTextToggleButton->setEnabled(false) ; hideChatTextToggleButton->setEnabled(false) ;
QIcon iconfullscreenToggleButton ; QIcon iconfullscreenToggleButton ;
iconfullscreenToggleButton.addPixmap(QPixmap(":/images/channels32.png")) ; iconfullscreenToggleButton.addPixmap(QPixmap(":/images/fullscreen_arrows.png")) ;
iconfullscreenToggleButton.addPixmap(QPixmap(":/images/folder-draft24.png"),QIcon::Normal,QIcon::On) ; iconfullscreenToggleButton.addPixmap(QPixmap(":/images/fullscreen.png"),QIcon::Normal,QIcon::On) ;
iconfullscreenToggleButton.addPixmap(QPixmap(":/images/folder-draft24.png"),QIcon::Disabled,QIcon::On) ; iconfullscreenToggleButton.addPixmap(QPixmap(":/images/fullscreen.png"),QIcon::Disabled,QIcon::On) ;
iconfullscreenToggleButton.addPixmap(QPixmap(":/images/folder-draft24.png"),QIcon::Active,QIcon::On) ; iconfullscreenToggleButton.addPixmap(QPixmap(":/images/fullscreen.png"),QIcon::Active,QIcon::On) ;
iconfullscreenToggleButton.addPixmap(QPixmap(":/images/folder-draft24.png"),QIcon::Selected,QIcon::On) ; iconfullscreenToggleButton.addPixmap(QPixmap(":/images/fullscreen.png"),QIcon::Selected,QIcon::On) ;
fullscreenToggleButton = new QToolButton ; fullscreenToggleButton = new QToolButton ;
fullscreenToggleButton->setIcon(iconfullscreenToggleButton) ; fullscreenToggleButton->setIcon(iconfullscreenToggleButton) ;
@ -236,7 +236,7 @@ VOIPChatWidgetHolder::VOIPChatWidgetHolder(ChatWidget *chatWidget, VOIPNotify *n
videoCaptureToggleButtonFS->setToolTip(tr("Start Video Call")); videoCaptureToggleButtonFS->setToolTip(tr("Start Video Call"));
hangupButtonFS = new QToolButton(fullScreenFrame) ; hangupButtonFS = new QToolButton(fullScreenFrame) ;
hangupButtonFS->setIcon(QIcon(":/images/call-stop.png")) ; hangupButtonFS->setIcon(QIcon(":/images/phone_hangup.png")) ;
hangupButtonFS->setIconSize(iconSize) ; hangupButtonFS->setIconSize(iconSize) ;
hangupButtonFS->setMinimumSize(buttonSize) ; hangupButtonFS->setMinimumSize(buttonSize) ;
hangupButtonFS->setMaximumSize(buttonSize) ; hangupButtonFS->setMaximumSize(buttonSize) ;

View File

@ -1,18 +1,19 @@
<RCC> <RCC>
<qresource prefix="/"> <qresource prefix="/">
<file>images/audio-volume-high.png</file>
<file>images/muted_self.svg</file> <file>images/muted_self.svg</file>
<file>images/audio-volume-muted.png</file>
<file>images/talking_on.svg</file> <file>images/talking_on.svg</file>
<file>images/talking_off.svg</file> <file>images/talking_off.svg</file>
<file>images/call-start.png</file> <file>images/chat-bubble.png</file>
<file>images/call-stop.png</file> <file>images/filmcam.png</file>
<file>images/call-hold.png</file> <file>images/fullscreen.png</file>
<file>images/camera-on.png</file> <file>images/fullscreen_arrows.png</file>
<file>images/camera-off.png</file> <file>images/microphone.png</file>
<file>images/microphone_mute.png</file>
<file>images/phone.png</file>
<file>images/phone_hangup.png</file>
<file>images/speaker.png</file>
<file>images/speaker_mute.png</file>
<file>images/webcam.png</file>
<file>images/video-icon-big.png</file> <file>images/video-icon-big.png</file>
<file>images/video-icon-on.png</file>
<file>images/video-icon-off.png</file>
</qresource> </qresource>
</RCC> </RCC>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 814 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 995 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -26,16 +26,16 @@
#include "rshare.h" #include "rshare.h"
#include "SearchDialog.h" #include "SearchDialog.h"
#include "RetroShareLink.h"
#include "msgs/MessageComposer.h"
#include "gui/RSHumanReadableDelegate.h" #include "gui/RSHumanReadableDelegate.h"
#include "gui/RetroShareLink.h"
#include "retroshare-gui/RsAutoUpdatePage.h" #include "retroshare-gui/RsAutoUpdatePage.h"
#include "gui/msgs/MessageComposer.h"
#include "gui/common/RsCollectionFile.h" #include "gui/common/RsCollectionFile.h"
#include "gui/common/FilesDefs.h" #include "gui/common/FilesDefs.h"
#include <gui/common/RsUrlHandler.h> #include "gui/common/RsUrlHandler.h"
#include "settings/rsharesettings.h" #include "gui/settings/rsharesettings.h"
#include "advsearch/advancedsearchdialog.h" #include "gui/advsearch/advancedsearchdialog.h"
#include "common/RSTreeWidgetItem.h" #include "gui/common/RSTreeWidgetItem.h"
#include "util/QtVersion.h" #include "util/QtVersion.h"
#include <retroshare/rsfiles.h> #include <retroshare/rsfiles.h>
@ -857,7 +857,7 @@ void SearchDialog::searchKeywords(const QString& keywords)
req_id = rsTurtle->turtleSearch(lin_exp) ; req_id = rsTurtle->turtleSearch(lin_exp) ;
} }
else else
req_id = ((((uint32_t)rand()) << 16)^0x1e2fd5e4) + (((uint32_t)rand())^0x1b19acfe) ; // generate a random 32 bits request id req_id = RSRandom::random_u32() ; // generate a random 32 bits request id
initSearchResult(keywords,req_id, ui.FileTypeComboBox->currentIndex(), false) ; // this will act before turtle results come to the interface, thanks to the signals scheduling policy. initSearchResult(keywords,req_id, ui.FileTypeComboBox->currentIndex(), false) ; // this will act before turtle results come to the interface, thanks to the signals scheduling policy.

View File

@ -43,7 +43,7 @@
#include "DLListDelegate.h" #include "DLListDelegate.h"
#include "ULListDelegate.h" #include "ULListDelegate.h"
#include "FileTransferInfoWidget.h" #include "FileTransferInfoWidget.h"
#include <gui/SearchDialog.h> #include <gui/FileTransfer/SearchDialog.h>
#include <gui/SharedFilesDialog.h> #include <gui/SharedFilesDialog.h>
#include "xprogressbar.h" #include "xprogressbar.h"
#include <gui/settings/rsharesettings.h> #include <gui/settings/rsharesettings.h>

View File

@ -955,13 +955,64 @@ void IdDialog::IdListCustomPopupMenu( QPoint )
std::list<RsGxsId> own_identities ; std::list<RsGxsId> own_identities ;
rsIdentity->getOwnIds(own_identities) ; rsIdentity->getOwnIds(own_identities) ;
QTreeWidgetItem *item = ui->idTreeWidget->currentItem(); // make some stats about what's selected. If the same value is used for all selected items, it can be switched.
if(item != allItem && item != contactsItem) { QList<QTreeWidgetItem *> selected_items = ui->idTreeWidget->selectedItems();
uint32_t item_flags = item->data(RSID_COL_KEYID,Qt::UserRole).toUInt() ;
if(!(item_flags & RSID_FILTER_OWNED_BY_YOU)) bool root_node_present = false ;
bool one_item_owned_by_you = false ;
uint32_t n_positive_reputations = 0 ;
uint32_t n_negative_reputations = 0 ;
uint32_t n_neutral_reputations = 0 ;
uint32_t n_is_a_contact = 0 ;
uint32_t n_is_not_a_contact = 0 ;
uint32_t n_selected_items =0 ;
for(QList<QTreeWidgetItem*>::const_iterator it(selected_items.begin());it!=selected_items.end();++it)
{ {
if(*it == allItem || *it == contactsItem)
{
root_node_present = true ;
continue ;
}
uint32_t item_flags = (*it)->data(RSID_COL_KEYID,Qt::UserRole).toUInt() ;
if(item_flags & RSID_FILTER_OWNED_BY_YOU)
one_item_owned_by_you = true ;
std::cerr << " item flags = " << item_flags << std::endl;
RsGxsId keyId((*it)->text(RSID_COL_KEYID).toStdString());
RsReputations::ReputationInfo info ;
rsReputations->getReputationInfo(keyId,info) ;
switch(info.mOwnOpinion)
{
case RsReputations::OPINION_NEGATIVE: ++n_negative_reputations ;
break ;
case RsReputations::OPINION_POSITIVE: ++n_positive_reputations ;
break ;
case RsReputations::OPINION_NEUTRAL: ++n_neutral_reputations ;
break ;
}
++n_selected_items ;
if(rsIdentity->isARegularContact(keyId))
++n_is_a_contact ;
else
++n_is_not_a_contact ;
}
if(root_node_present) // don't show menu if some of the root nodes are present
return ;
if(!one_item_owned_by_you)
{
if(n_selected_items == 1) // if only one item is selected, allow to chat with this item
if(own_identities.size() <= 1) if(own_identities.size() <= 1)
{ {
QAction *action = contextMnu.addAction(QIcon(":/images/chat_24.png"), tr("Chat with this person"), this, SLOT(chatIdentity())); QAction *action = contextMnu.addAction(QIcon(":/images/chat_24.png"), tr("Chat with this person"), this, SLOT(chatIdentity()));
@ -990,54 +1041,31 @@ void IdDialog::IdListCustomPopupMenu( QPoint )
} }
} }
contextMnu.addAction(QIcon(":/images/mail_new.png"), tr("Send message to this person"), this, SLOT(sendMsg())); // always allow to send messages
contextMnu.addAction(QIcon(":/images/mail_new.png"), tr("Send message"), this, SLOT(sendMsg()));
contextMnu.addSeparator(); contextMnu.addSeparator();
RsIdentityDetails details; if(n_is_a_contact == 0)
std::string keyId = item->text(RSID_COL_KEYID).toStdString(); contextMnu.addAction(QIcon(), tr("Add to Contacts"), this, SLOT(addtoContacts()));
rsIdentity->getIdDetails(RsGxsId(keyId), details); if(n_is_not_a_contact == 0)
contextMnu.addAction(QIcon(":/images/cancel.png"), tr("Remove from Contacts"), this, SLOT(removefromContacts()));
QAction *addContact = contextMnu.addAction(QIcon(), tr("Add to Contacts"), this, SLOT(addtoContacts()));
QAction *removeContact = contextMnu.addAction(QIcon(":/images/cancel.png"), tr("Remove from Contacts"), this, SLOT(removefromContacts()));
if(details.mFlags & RS_IDENTITY_FLAGS_IS_A_CONTACT)
{
addContact->setVisible(false);
removeContact->setVisible(true);
}
else
{
addContact->setVisible(true);
removeContact->setVisible(false);
}
contextMnu.addSeparator(); contextMnu.addSeparator();
RsReputations::ReputationInfo info ; if(n_positive_reputations == 0) // only unban when all items are banned
std::string Id = item->text(RSID_COL_KEYID).toStdString(); contextMnu.addAction(QIcon(), tr("Set positive opinion"), this, SLOT(positivePerson()));
rsReputations->getReputationInfo(RsGxsId(Id),info) ;
if(n_neutral_reputations == 0) // only unban when all items are banned
contextMnu.addAction(QIcon(), tr("Set neutral opinion"), this, SLOT(neutralPerson()));
QAction *banaction = contextMnu.addAction(QIcon(":/images/denied16.png"), tr("Ban this person"), this, SLOT(banPerson())); if(n_negative_reputations == 0)
QAction *unbanaction = contextMnu.addAction(QIcon(), tr("Unban this person"), this, SLOT(unbanPerson())); contextMnu.addAction(QIcon(":/images/denied16.png"), tr("Set negative opinion"), this, SLOT(negativePerson()));
}
if(one_item_owned_by_you && n_selected_items==1)
if(info.mAssessment == RsReputations::ASSESSMENT_BAD)
{ {
banaction->setVisible(false);
unbanaction->setVisible(true);
}
else
{
banaction->setVisible(true);
unbanaction->setVisible(false);
}
}
contextMnu.addSeparator(); contextMnu.addSeparator();
contextMnu.addAction(ui->editIdentity); contextMnu.addAction(ui->editIdentity);
@ -1076,25 +1104,27 @@ void IdDialog::chatIdentity()
void IdDialog::sendMsg() void IdDialog::sendMsg()
{ {
QTreeWidgetItem *item = ui->idTreeWidget->currentItem(); QList<QTreeWidgetItem *> selected_items = ui->idTreeWidget->selectedItems();
if (!item)
{ if(selected_items.empty())
return ; return ;
}
MessageComposer *nMsgDialog = MessageComposer::newMsg(); MessageComposer *nMsgDialog = MessageComposer::newMsg();
if (nMsgDialog == NULL) { if (nMsgDialog == NULL)
return; return;
}
for(QList<QTreeWidgetItem*>::const_iterator it(selected_items.begin());it!=selected_items.end();++it)
{
QTreeWidgetItem *item = *it ;
std::string keyId = item->text(RSID_COL_KEYID).toStdString(); std::string keyId = item->text(RSID_COL_KEYID).toStdString();
nMsgDialog->addRecipient(MessageComposer::TO, RsGxsId(keyId)); nMsgDialog->addRecipient(MessageComposer::TO, RsGxsId(keyId));
}
nMsgDialog->show(); nMsgDialog->show();
nMsgDialog->activateWindow(); nMsgDialog->activateWindow();
/* window will destroy itself! */ /* window will destroy itself! */
} }
QString IdDialog::inviteMessage() QString IdDialog::inviteMessage()
@ -1133,33 +1163,48 @@ void IdDialog::sendInvite()
} }
void IdDialog::banPerson() void IdDialog::negativePerson()
{ {
QTreeWidgetItem *item = ui->idTreeWidget->currentItem(); QList<QTreeWidgetItem *> selected_items = ui->idTreeWidget->selectedItems();
if (!item) for(QList<QTreeWidgetItem*>::const_iterator it(selected_items.begin());it!=selected_items.end();++it)
{ {
return; QTreeWidgetItem *item = *it ;
}
std::string Id = item->text(RSID_COL_KEYID).toStdString(); std::string Id = item->text(RSID_COL_KEYID).toStdString();
rsReputations->setOwnOpinion(RsGxsId(Id),RsReputations::OPINION_NEGATIVE) ; rsReputations->setOwnOpinion(RsGxsId(Id),RsReputations::OPINION_NEGATIVE) ;
}
requestIdDetails(); requestIdDetails();
requestIdList(); requestIdList();
} }
void IdDialog::unbanPerson() void IdDialog::neutralPerson()
{ {
QTreeWidgetItem *item = ui->idTreeWidget->currentItem(); QList<QTreeWidgetItem *> selected_items = ui->idTreeWidget->selectedItems();
if (!item) for(QList<QTreeWidgetItem*>::const_iterator it(selected_items.begin());it!=selected_items.end();++it)
{ {
return; QTreeWidgetItem *item = *it ;
std::string Id = item->text(RSID_COL_KEYID).toStdString();
rsReputations->setOwnOpinion(RsGxsId(Id),RsReputations::OPINION_NEUTRAL) ;
} }
requestIdDetails();
requestIdList();
}
void IdDialog::positivePerson()
{
QList<QTreeWidgetItem *> selected_items = ui->idTreeWidget->selectedItems();
for(QList<QTreeWidgetItem*>::const_iterator it(selected_items.begin());it!=selected_items.end();++it)
{
QTreeWidgetItem *item = *it ;
std::string Id = item->text(RSID_COL_KEYID).toStdString(); std::string Id = item->text(RSID_COL_KEYID).toStdString();
rsReputations->setOwnOpinion(RsGxsId(Id),RsReputations::OPINION_POSITIVE) ; rsReputations->setOwnOpinion(RsGxsId(Id),RsReputations::OPINION_POSITIVE) ;
}
requestIdDetails(); requestIdDetails();
requestIdList(); requestIdList();
@ -1167,30 +1212,28 @@ void IdDialog::unbanPerson()
void IdDialog::addtoContacts() void IdDialog::addtoContacts()
{ {
QTreeWidgetItem *item = ui->idTreeWidget->currentItem(); QList<QTreeWidgetItem *> selected_items = ui->idTreeWidget->selectedItems();
if (!item) for(QList<QTreeWidgetItem*>::const_iterator it(selected_items.begin());it!=selected_items.end();++it)
{ {
return; QTreeWidgetItem *item = *it ;
}
std::string Id = item->text(RSID_COL_KEYID).toStdString(); std::string Id = item->text(RSID_COL_KEYID).toStdString();
rsIdentity->setAsRegularContact(RsGxsId(Id),true); rsIdentity->setAsRegularContact(RsGxsId(Id),true);
}
requestIdList(); requestIdList();
} }
void IdDialog::removefromContacts() void IdDialog::removefromContacts()
{ {
QTreeWidgetItem *item = ui->idTreeWidget->currentItem(); QList<QTreeWidgetItem *> selected_items = ui->idTreeWidget->selectedItems();
if (!item) for(QList<QTreeWidgetItem*>::const_iterator it(selected_items.begin());it!=selected_items.end();++it)
{ {
return; QTreeWidgetItem *item = *it ;
}
std::string Id = item->text(RSID_COL_KEYID).toStdString(); std::string Id = item->text(RSID_COL_KEYID).toStdString();
rsIdentity->setAsRegularContact(RsGxsId(Id),false); rsIdentity->setAsRegularContact(RsGxsId(Id),false);
}
requestIdList(); requestIdList();
} }

View File

@ -77,8 +77,9 @@ private slots:
void addtoContacts(); void addtoContacts();
void removefromContacts(); void removefromContacts();
void banPerson(); void negativePerson();
void unbanPerson(); void positivePerson();
void neutralPerson();
static QString inviteMessage(); static QString inviteMessage();
void sendInvite(); void sendInvite();

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>745</width> <width>745</width>
<height>500</height> <height>634</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -20,21 +20,12 @@
<string/> <string/>
</property> </property>
<layout class="QGridLayout" name="gridLayout_5"> <layout class="QGridLayout" name="gridLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="horizontalSpacing"> <property name="horizontalSpacing">
<number>0</number> <number>0</number>
</property> </property>
<property name="margin">
<number>0</number>
</property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QFrame" name="titleBarFrame"> <widget class="QFrame" name="titleBarFrame">
<property name="sizePolicy"> <property name="sizePolicy">
@ -50,16 +41,7 @@
<enum>QFrame::Sunken</enum> <enum>QFrame::Sunken</enum>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin"> <property name="margin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number> <number>2</number>
</property> </property>
<item> <item>
@ -150,16 +132,7 @@
<enum>QFrame::Sunken</enum> <enum>QFrame::Sunken</enum>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin"> <property name="margin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number> <number>2</number>
</property> </property>
<item> <item>
@ -255,7 +228,7 @@
<string>Reputation</string> <string>Reputation</string>
</property> </property>
<property name="textAlignment"> <property name="textAlignment">
<set>AlignLeading|AlignVCenter</set> <set>AlignLeft|AlignVCenter</set>
</property> </property>
</column> </column>
</widget> </widget>
@ -319,16 +292,7 @@
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0"> <item row="0" column="0">
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<property name="leftMargin"> <property name="margin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number> <number>6</number>
</property> </property>
<property name="spacing"> <property name="spacing">
@ -485,6 +449,19 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="1" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -502,16 +479,7 @@
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin"> <property name="margin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number> <number>6</number>
</property> </property>
<item row="2" column="1"> <item row="2" column="1">

View File

@ -1,3 +1,5 @@
#include <QToolButton>
#include <retroshare-gui/mainpage.h> #include <retroshare-gui/mainpage.h>
#include "common/FloatingHelpBrowser.h" #include "common/FloatingHelpBrowser.h"
@ -9,12 +11,13 @@ MainPage::MainPage(QWidget *parent , Qt::WindowFlags flags ) : QWidget(parent, f
mHelp = ""; mHelp = "";
} }
void MainPage::registerHelpButton(QAbstractButton *button,const QString& help_html_txt) void MainPage::registerHelpButton(QToolButton *button,const QString& help_html_txt)
{ {
if (mHelpBrowser == NULL) if (mHelpBrowser == NULL)
{
mHelpBrowser = new FloatingHelpBrowser(this, button) ; mHelpBrowser = new FloatingHelpBrowser(this, button) ;
}
float S = QFontMetricsF(button->font()).height() ;
button->setIconSize(QSize(S,S)) ;
mHelpBrowser->setHelpText(help_html_txt) ; mHelpBrowser->setHelpText(help_html_txt) ;
} }

View File

@ -40,7 +40,7 @@
#include "ui_MainWindow.h" #include "ui_MainWindow.h"
#include "MessengerWindow.h" #include "MessengerWindow.h"
#include "NetworkDialog.h" #include "NetworkDialog.h"
#include "SearchDialog.h" #include "gui/FileTransfer/SearchDialog.h"
#include "gui/FileTransfer/TransfersDialog.h" #include "gui/FileTransfer/TransfersDialog.h"
#include "MessagesDialog.h" #include "MessagesDialog.h"
#include "SharedFilesDialog.h" #include "SharedFilesDialog.h"

View File

@ -43,7 +43,7 @@ NetworkView::NetworkView(QWidget *parent)
mScene = new QGraphicsScene(); mScene = new QGraphicsScene();
mScene->setItemIndexMethod(QGraphicsScene::NoIndex); mScene->setItemIndexMethod(QGraphicsScene::NoIndex);
mScene->setSceneRect(-200, -200, 1200, 1200); mScene->setSceneRect(0, 0, ui.graphicsView->width(), ui.graphicsView->height());
ui.graphicsView->setScene(mScene); ui.graphicsView->setScene(mScene);
ui.graphicsView->setEdgeLength(ui.edgeLengthSB->value()) ; ui.graphicsView->setEdgeLength(ui.edgeLengthSB->value()) ;

View File

@ -91,8 +91,8 @@
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="icons.qrc"> <iconset resource="images.qrc">
<normaloff>:/icons/information_128.png</normaloff>:/icons/information_128.png</iconset> <normaloff>:/icons/help_64.png</normaloff>:/icons/help_64.png</iconset>
</property> </property>
<property name="iconSize"> <property name="iconSize">
<size> <size>

View File

@ -38,7 +38,7 @@
#include "MainWindow.h" #include "MainWindow.h"
#include "gui/gxsforums/GxsForumsDialog.h" #include "gui/gxsforums/GxsForumsDialog.h"
#include "gui/gxschannels/GxsChannelDialog.h" #include "gui/gxschannels/GxsChannelDialog.h"
#include "SearchDialog.h" #include "gui/FileTransfer/SearchDialog.h"
#include "msgs/MessageComposer.h" #include "msgs/MessageComposer.h"
#include "util/misc.h" #include "util/misc.h"
#include "common/PeerDefs.h" #include "common/PeerDefs.h"

View File

@ -20,6 +20,8 @@
****************************************************************/ ****************************************************************/
#include <QApplication> #include <QApplication>
#include <QFile>
#include <QProcess>
#include <QSound> #include <QSound>
#include <QDir> #include <QDir>
@ -28,6 +30,10 @@
#include <QAudioDeviceInfo> #include <QAudioDeviceInfo>
#endif #endif
// #ifdef QMEDIAPLAYER
// #nclude <QMediaPlayer>
// #endif
#include "SoundManager.h" #include "SoundManager.h"
#include "settings/rsharesettings.h" #include "settings/rsharesettings.h"
#include "retroshare/rsinit.h" #include "retroshare/rsinit.h"
@ -234,12 +240,60 @@ void SoundManager::playFile(const QString &filename)
} }
QString playFilename = realFilename(filename); QString playFilename = realFilename(filename);
bool played = false ;
#if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) #if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0)
if (!QAudioDeviceInfo::availableDevices(QAudio::AudioOutput).isEmpty()) { if (!QAudioDeviceInfo::availableDevices(QAudio::AudioOutput).isEmpty())
#else #else
if (QSound::isAvailable()) { if (QSound::isAvailable())
#endif #endif
{
QSound::play(playFilename); QSound::play(playFilename);
played = true ;
}
if(!played) // let's go for the hard core stuff
{
// #ifdef QMEDIAPLAYER
// static QMediaPlayer *qmplayer;
// if (qmplayer == NULL) {
// qmplayer = new QMediaPlayer();
// qmplayer->setMedia(QMediaContent(QUrl::fromLocalFile(playFilename)));
// }
// std::cerr << "Play QMediaPlayer" << std::endl;
// qmplayer->play();
// return;
// #endif
#ifdef Q_OS_LINUX
QString player_cmd = soundDetectPlayer();
QStringList args = player_cmd.split(' ');
args += filename;
QString prog = args.takeFirst();
//std::cerr << "Play " << prog.toStdString() << std::endl;
QProcess::startDetached(prog, args);
#endif
} }
} }
#ifdef Q_OS_LINUX
/** Detect default player helper on unix like systems
* Inspired by Psi IM (0.15) in common.cpp
*/
QString SoundManager::soundDetectPlayer()
{
// prefer ALSA on linux
if (QFile("/proc/asound").exists()) {
return "aplay -q";
}
// fallback to "play"
return "play";
}
#endif

View File

@ -67,6 +67,10 @@ signals:
public: public:
static void create(); static void create();
#ifdef Q_OS_LINUX
static QString soundDetectPlayer();
#endif
static void initDefault(); static void initDefault();
static QString defaultFilename(const QString &event, bool check); static QString defaultFilename(const QString &event, bool check);
static QString convertFilename(const QString &filename); static QString convertFilename(const QString &filename);

View File

@ -1657,7 +1657,7 @@ void ChatWidget::updatePeersCustomStateString(const QString& /*peer_id*/, const
void ChatWidget::updateStatusString(const QString &statusMask, const QString &statusString, bool permanent) void ChatWidget::updateStatusString(const QString &statusMask, const QString &statusString, bool permanent)
{ {
ui->typingLabel->setText(QString(statusMask).arg(tr(statusString.toLatin1()))); // displays info for 5 secs. ui->typingLabel->setText(QString(statusMask).arg(tr(statusString.toUtf8()))); // displays info for 5 secs.
ui->typingpixmapLabel->setPixmap(QPixmap(":images/typing.png") ); ui->typingpixmapLabel->setPixmap(QPixmap(":images/typing.png") );
if (statusString == "is typing...") { if (statusString == "is typing...") {
@ -1693,6 +1693,7 @@ void ChatWidget::quote()
{ {
QStringList sl = text.split(QRegExp("[\r\n]"),QString::SkipEmptyParts); QStringList sl = text.split(QRegExp("[\r\n]"),QString::SkipEmptyParts);
text = sl.join("\n>"); text = sl.join("\n>");
text.replace(QChar(-4),"");//Char used when image on text.
emit ui->chatTextEdit->append(QString(">") + text); emit ui->chatTextEdit->append(QString(">") + text);
} }
} }

View File

@ -269,7 +269,7 @@ void MimeTextEdit::pasteOwnCertificateLink()
void MimeTextEdit::pastePlainText() void MimeTextEdit::pastePlainText()
{ {
insertPlainText(QApplication::clipboard()->text()); insertPlainText(QApplication::clipboard()->text().remove(QChar(-4)));//Char used when image on text.
} }
void MimeTextEdit::spoiler() void MimeTextEdit::spoiler()

View File

@ -127,7 +127,8 @@ GraphWidget::GraphWidget(QWidget *)
// scene->setItemIndexMethod(QGraphicsScene::NoIndex); // scene->setItemIndexMethod(QGraphicsScene::NoIndex);
// scene->clear() ; // scene->clear() ;
// setScene(scene); // setScene(scene);
// scene->setSceneRect(0, 0, 500, 500);
// scene()->setSceneRect(0, 0, width(), height());
setCacheMode(CacheBackground); setCacheMode(CacheBackground);
setViewportUpdateMode(BoundingRectViewportUpdate); setViewportUpdateMode(BoundingRectViewportUpdate);
@ -154,7 +155,8 @@ void GraphWidget::clearGraph()
// } // }
scene()->clear(); scene()->clear();
scene()->setSceneRect(-200, -200, 1000, 1000); scene()->setSceneRect(0, 0, width(), height());
_edges.clear(); _edges.clear();
_nodes.clear(); _nodes.clear();
_friction_factor = 1.0f ; _friction_factor = 1.0f ;
@ -391,9 +393,11 @@ void GraphWidget::setEdgeLength(uint32_t l)
void GraphWidget::setNameSearch(QString s) void GraphWidget::setNameSearch(QString s)
{ {
float f = QFontMetrics(font()).height()/16.0 ;
if (s.length() == 0){ if (s.length() == 0){
for(uint32_t i=0;i<_nodes.size();++i) for(uint32_t i=0;i<_nodes.size();++i)
_nodes[i]->setNodeDrawSize(20); _nodes[i]->setNodeDrawSize(12 * f);
forceRedraw(); forceRedraw();
return; return;
} }
@ -405,10 +409,10 @@ void GraphWidget::setNameSearch(QString s)
if (ns.find(qs) != std::string::npos) { if (ns.find(qs) != std::string::npos) {
//std::cout << "found!" << '\n'; //std::cout << "found!" << '\n';
ni->setNodeDrawSize(22); ni->setNodeDrawSize(22 * f);
//std::cout << ni->getNodeDrawSize() << '\n'; //std::cout << ni->getNodeDrawSize() << '\n';
} else { } else {
ni->setNodeDrawSize(12); ni->setNodeDrawSize(12 * f);
} }
} }
@ -420,47 +424,53 @@ void GraphWidget::forceRedraw()
for(uint32_t i=0;i<_nodes.size();++i) for(uint32_t i=0;i<_nodes.size();++i)
_nodes[i]->update(_nodes[i]->boundingRect()) ; _nodes[i]->update(_nodes[i]->boundingRect()) ;
} }
void GraphWidget::resizeEvent(QResizeEvent *event)
{
scene()->setSceneRect(QRectF(QPointF(0,0),event->size()));
}
void GraphWidget::wheelEvent(QWheelEvent *event) void GraphWidget::wheelEvent(QWheelEvent *event)
{ {
scaleView(pow((double)2, -event->delta() / 240.0)); scaleView(pow((double)2, -event->delta() / 240.0));
} }
void GraphWidget::drawBackground(QPainter *painter, const QRectF &rect) //void GraphWidget::drawBackground(QPainter *painter, const QRectF &rect)
{ //{
Q_UNUSED(rect); // Q_UNUSED(rect);
//
// Shadow // // Shadow
QRectF sceneRect = this->sceneRect(); // QRectF sceneRect = this->sceneRect();
QRectF rightShadow(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height()); // QRectF rightShadow(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height());
QRectF bottomShadow(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5); // QRectF bottomShadow(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5);
if (rightShadow.intersects(rect) || rightShadow.contains(rect)) // if (rightShadow.intersects(rect) || rightShadow.contains(rect))
painter->fillRect(rightShadow, Qt::darkGray); // painter->fillRect(rightShadow, Qt::darkGray);
if (bottomShadow.intersects(rect) || bottomShadow.contains(rect)) // if (bottomShadow.intersects(rect) || bottomShadow.contains(rect))
painter->fillRect(bottomShadow, Qt::darkGray); // painter->fillRect(bottomShadow, Qt::darkGray);
//
// Fill // // Fill
QLinearGradient gradient(sceneRect.topLeft(), sceneRect.bottomRight()); // QLinearGradient gradient(sceneRect.topLeft(), sceneRect.bottomRight());
gradient.setColorAt(0, Qt::white); // gradient.setColorAt(0, Qt::white);
gradient.setColorAt(1, Qt::lightGray); // gradient.setColorAt(1, Qt::lightGray);
painter->fillRect(rect.intersected(sceneRect), gradient); // painter->fillRect(rect.intersected(sceneRect), gradient);
painter->setBrush(Qt::NoBrush); // painter->setBrush(Qt::NoBrush);
painter->drawRect(sceneRect); // painter->drawRect(sceneRect);
//
// Text // // Text
QRectF textRect(sceneRect.left() + 4, sceneRect.top() + 4, // QRectF textRect(sceneRect.left() + 4, sceneRect.top() + 4,
sceneRect.width() - 4, sceneRect.height() - 4); // sceneRect.width() - 4, sceneRect.height() - 4);
QString message(tr("Click and drag the nodes around, and zoom with the mouse " // QString message(tr("Click and drag the nodes around, and zoom with the mouse "
"wheel or the '+' and '-' keys")); // "wheel or the '+' and '-' keys"));
//
QFont font = painter->font(); // QFont font = painter->font();
font.setBold(true); // font.setBold(true);
font.setPointSize(14); // font.setPointSize(14);
painter->setFont(font); // painter->setFont(font);
painter->setPen(Qt::lightGray); // painter->setPen(Qt::lightGray);
painter->drawText(textRect.translated(2, 2), message); // painter->drawText(textRect.translated(2, 2), message);
painter->setPen(Qt::black); // painter->setPen(Qt::black);
painter->drawText(textRect, message); // painter->drawText(textRect, message);
} //}
void GraphWidget::scaleView(qreal scaleFactor) void GraphWidget::scaleView(qreal scaleFactor)
{ {

View File

@ -91,10 +91,11 @@ public:
void forceRedraw() ; void forceRedraw() ;
protected: protected:
void keyPressEvent(QKeyEvent *event); virtual void keyPressEvent(QKeyEvent *event);
void timerEvent(QTimerEvent *event); virtual void timerEvent(QTimerEvent *event);
void wheelEvent(QWheelEvent *event); virtual void wheelEvent(QWheelEvent *event);
void drawBackground(QPainter *painter, const QRectF &rect); virtual void resizeEvent(QResizeEvent *event);
//void drawBackground(QPainter *painter, const QRectF &rect);
void scaleView(qreal scaleFactor); void scaleView(qreal scaleFactor);

View File

@ -205,8 +205,8 @@ void Node::calculateForces(const double *map,int width,int height,int W,int H,fl
QRectF sceneRect = scene()->sceneRect(); QRectF sceneRect = scene()->sceneRect();
newPos = pos() + QPointF(_speedx, _speedy) / friction_factor; newPos = pos() + QPointF(_speedx, _speedy) / friction_factor;
newPos.setX(qMin(qMax(newPos.x(), sceneRect.left() + 10), sceneRect.right() - 10)); newPos.setX(qMin(qMax(newPos.x(), sceneRect.left()), sceneRect.right()));
newPos.setY(qMin(qMax(newPos.y(), sceneRect.top() + 10), sceneRect.bottom() - 10)); newPos.setY(qMin(qMax(newPos.y(), sceneRect.top()) , sceneRect.bottom()));
} }
bool Node::advance() bool Node::advance()
@ -222,20 +222,22 @@ bool Node::advance()
QRectF Node::boundingRect() const QRectF Node::boundingRect() const
{ {
qreal adjust = 2; float m = QFontMetricsF(graph->font()).height();
float f = m/16.0;
qreal adjust = 2*f;
/* add in the size of the text */ /* add in the size of the text */
qreal realwidth = 40; qreal realwidth = 40*f;
if (mDeterminedBB) if (mDeterminedBB)
{ {
realwidth = mBBWidth + adjust; realwidth = mBBWidth + adjust;
} }
if (realwidth < 23 + adjust) if (realwidth < 23*f + adjust)
{ {
realwidth = 23 + adjust; realwidth = 23*f + adjust;
} }
return QRectF(-10 - adjust, -10 - adjust, return QRectF(-10*f - adjust, -10*f - adjust, realwidth, 23*f + adjust);
realwidth, 23 + adjust);
} }
QPainterPath Node::shape() const QPainterPath Node::shape() const
@ -314,12 +316,17 @@ void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid
painter->setBrush(gradient); painter->setBrush(gradient);
painter->setPen(QPen(Qt::black, 0)); painter->setPen(QPen(Qt::black, 0));
painter->drawEllipse(-mNodeDrawSize2, -mNodeDrawSize2, mNodeDrawSize, mNodeDrawSize); painter->drawEllipse(-mNodeDrawSize2, -mNodeDrawSize2, mNodeDrawSize, mNodeDrawSize);
painter->drawText(-10, 0, QString::fromUtf8(_desc_string.c_str()));
QString txt = QString::fromUtf8(_desc_string.c_str());
float m = QFontMetricsF(graph->font()).height();
float f = m/16.0;
painter->drawText(-10, 5*f, txt) ;
if (!mDeterminedBB) if (!mDeterminedBB)
{ {
QRect textBox = painter->boundingRect(-10, 0, 400, 20, 0, QString::fromUtf8(_desc_string.c_str())); QRect textBox = painter->boundingRect(-10, 5*f, QFontMetricsF(graph->font()).width(txt), 1.5*m, Qt::AlignVCenter, QString::fromUtf8(_desc_string.c_str()));
mBBWidth = textBox.width(); mBBWidth = textBox.width()+40*f;
mDeterminedBB = true; mDeterminedBB = true;
} }
} }

View File

@ -3,6 +3,9 @@
<file>icons/add_user_256.png</file> <file>icons/add_user_256.png</file>
<file>icons/anonymous_blue_128.png</file> <file>icons/anonymous_blue_128.png</file>
<file>icons/anonymous_green_128.png</file> <file>icons/anonymous_green_128.png</file>
<file>icons/aol.png</file>
<file>icons/avatar_128.png</file>
<file>icons/avatar_grey_128.png</file>
<file>icons/blank_blue_128.png</file> <file>icons/blank_blue_128.png</file>
<file>icons/blank_green_128.png</file> <file>icons/blank_green_128.png</file>
<file>icons/browsable_blue_128.png</file> <file>icons/browsable_blue_128.png</file>
@ -19,6 +22,7 @@
<file>icons/friends_128.png</file> <file>icons/friends_128.png</file>
<file>icons/global_switch_off_128.png</file> <file>icons/global_switch_off_128.png</file>
<file>icons/global_switch_on_128.png</file> <file>icons/global_switch_on_128.png</file>
<file>icons/gmail.png</file>
<file>icons/help_128.png</file> <file>icons/help_128.png</file>
<file>icons/help_64.png</file> <file>icons/help_64.png</file>
<file>icons/information_128.png</file> <file>icons/information_128.png</file>
@ -38,6 +42,7 @@
<file>icons/mail_old_128.png</file> <file>icons/mail_old_128.png</file>
<file>icons/mail_red_128.png</file> <file>icons/mail_red_128.png</file>
<file>icons/newsfeed128.png</file> <file>icons/newsfeed128.png</file>
<file>icons/outlook.png</file>
<file>icons/plugins_128.png</file> <file>icons/plugins_128.png</file>
<file>icons/posted_128.png</file> <file>icons/posted_128.png</file>
<file>icons/posted_red_128.png</file> <file>icons/posted_red_128.png</file>
@ -55,19 +60,18 @@
<file>icons/tile_downloaded_48.png</file> <file>icons/tile_downloaded_48.png</file>
<file>icons/tile_downloading_48.png</file> <file>icons/tile_downloading_48.png</file>
<file>icons/tile_inactive_48.png</file> <file>icons/tile_inactive_48.png</file>
<file>icons/tor-logo.png</file>
<file>icons/tor-off.png</file>
<file>icons/tor-on.png</file>
<file>icons/tor-starting.png</file>
<file>icons/tor-stopping.png</file>
<file>icons/user-away_64.png</file> <file>icons/user-away_64.png</file>
<file>icons/user-away-extended_64.png</file> <file>icons/user-away-extended_64.png</file>
<file>icons/user-busy_64.png</file> <file>icons/user-busy_64.png</file>
<file>icons/user-offline_64.png</file> <file>icons/user-offline_64.png</file>
<file>icons/user-online_64.png</file> <file>icons/user-online_64.png</file>
<file>icons/yellow_biohazard64.png</file>
<file>icons/gmail.png</file>
<file>icons/yahoo.png</file> <file>icons/yahoo.png</file>
<file>icons/outlook.png</file>
<file>icons/aol.png</file>
<file>icons/yandex.png</file> <file>icons/yandex.png</file>
<file>icons/tor-on.png</file> <file>icons/yellow_biohazard64.png</file>
<file>icons/tor-logo.png</file>
<file>icons/tor-off.png</file>
</qresource> </qresource>
</RCC> </RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

@ -17,6 +17,41 @@
</sizepolicy> </sizepolicy>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Distant messages:</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="2">
<widget class="QComboBox" name="comboBox">
<item>
<property name="text">
<string>Everyone</string>
</property>
</item>
<item>
<property name="text">
<string>Contacts</string>
</property>
</item>
<item>
<property name="text">
<string>Nobody</string>
</property>
</item>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Accept encrypted distant messages from</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">
<property name="title"> <property name="title">
@ -54,41 +89,6 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Distant messages:</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="2">
<widget class="QComboBox" name="comboBox">
<item>
<property name="text">
<string>Everyone</string>
</property>
</item>
<item>
<property name="text">
<string>Contacts</string>
</property>
</item>
<item>
<property name="text">
<string>Nobody</string>
</property>
</item>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Accept encrypted distant messages from</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QGroupBox" name="groupBox_2"> <widget class="QGroupBox" name="groupBox_2">
<property name="title"> <property name="title">

View File

@ -27,9 +27,6 @@
<string>Plugins</string> <string>Plugins</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_4"> <layout class="QVBoxLayout" name="verticalLayout_4">
<property name="margin">
<number>6</number>
</property>
<item> <item>
<widget class="QScrollArea" name="scrollArea"> <widget class="QScrollArea" name="scrollArea">
<property name="frameShape"> <property name="frameShape">
@ -43,7 +40,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>391</width> <width>920</width>
<height>16</height> <height>16</height>
</rect> </rect>
</property> </property>
@ -74,20 +71,7 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="QTextBrowser" name="_lookupDirectories_TB"> <widget class="QTextBrowser" name="_lookupDirectories_TB"/>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>

View File

@ -798,6 +798,9 @@ behind a firewall or a VPN.</string>
</item> </item>
<item> <item>
<widget class="QSpinBox" name="hiddenpage_proxyPort_tor"> <widget class="QSpinBox" name="hiddenpage_proxyPort_tor">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This is the port of the Tor Socks proxy. Your Retroshare node can use this port to connect to&lt;/p&gt;&lt;p&gt;Hidden nodes. The led at right turns green when this port is active on your computer. &lt;/p&gt;&lt;p&gt;This does not mean however that your Retroshare traffic transits though Tor. It does only if &lt;/p&gt;&lt;p&gt;you connect to Hidden nodes, or if you are running a Hidden node yourself.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="minimum"> <property name="minimum">
<number>10</number> <number>10</number>
</property> </property>
@ -828,6 +831,9 @@ behind a firewall or a VPN.</string>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_9"> <widget class="QLabel" name="label_9">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This led is green when the port listen on the left is active on your computer. It does not&lt;/p&gt;&lt;p&gt;mean that your Retroshare traffic transits though Tor. It will do so only if &lt;/p&gt;&lt;p&gt;you connect to Hidden nodes, or if you are running a Hidden node yourself.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>Tor outgoing Okay</string> <string>Tor outgoing Okay</string>
</property> </property>
@ -859,6 +865,9 @@ behind a firewall or a VPN.</string>
</item> </item>
<item> <item>
<widget class="QSpinBox" name="hiddenpage_proxyPort_i2p"> <widget class="QSpinBox" name="hiddenpage_proxyPort_i2p">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This is the port of the I2P Socks proxy. Your Retroshare node can use this port to connect to&lt;/p&gt;&lt;p&gt;Hidden nodes. The led at right turns green when this port is active on your computer. &lt;/p&gt;&lt;p&gt;This does not mean however that your Retroshare traffic transits though I2P. It does only if &lt;/p&gt;&lt;p&gt;you connect to Hidden nodes, or if you are running a Hidden node yourself.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="minimum"> <property name="minimum">
<number>10</number> <number>10</number>
</property> </property>
@ -883,6 +892,9 @@ behind a firewall or a VPN.</string>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This led is green when the port listen on the left is active on your computer. It does not&lt;/p&gt;&lt;p&gt;mean that your Retroshare traffic transits though I2P. It will do so only if &lt;/p&gt;&lt;p&gt;you connect to Hidden nodes, or if you are running a Hidden node yourself.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>I2P outgoing Okay</string> <string>I2P outgoing Okay</string>
</property> </property>
@ -949,7 +961,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
<item> <item>
<widget class="QPushButton" name="testIncoming_PB"> <widget class="QPushButton" name="testIncoming_PB">
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This button simulates a SSL connection to your hidden address using the corresponding proxy. If your hidden node is reachable, it should cause a SSL handshake error, which RS will interpret as a valid connection state. This operation might also cause several &amp;quot;security warning&amp;quot; about connections from your local host IP (127.0.0.1) in the News Feed if you enabled it,&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This button simulates a SSL connection to your hidden address using the corresponding proxy. If your hidden node is reachable, it should cause a SSL handshake error, which RS will interpret as a valid connection state. This operation might also cause several &amp;quot;security warning&amp;quot; about connections from your local host IP (127.0.0.1) in the News Feed if you enabled it, which you should interpret as a sign of good communication.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Test</string> <string>Test</string>
@ -1016,6 +1028,9 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
</item> </item>
<item> <item>
<widget class="QLabel" name="l_incomingTestResult"> <widget class="QLabel" name="l_incomingTestResult">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This led turns green only if you launch an active test using the above button. &lt;/p&gt;&lt;p&gt;When it does, it means that your hidden node can be reached from anywhere, using the Tor (resp. I2P) &lt;/p&gt;&lt;p&gt;network. Congratulations!&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>incoming ok</string> <string>incoming ok</string>
</property> </property>

View File

@ -23,16 +23,7 @@
<property name="spacing"> <property name="spacing">
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin"> <property name="margin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
@ -106,29 +97,17 @@
</item> </item>
<item row="0" column="0" rowspan="3"> <item row="0" column="0" rowspan="3">
<widget class="QListWidget" name="listWidget"> <widget class="QListWidget" name="listWidget">
<property name="minimumSize"> <property name="sizePolicy">
<size> <sizepolicy hsizetype="Maximum" vsizetype="Expanding">
<width>130</width> <horstretch>0</horstretch>
<height>0</height> <verstretch>0</verstretch>
</size> </sizepolicy>
</property> </property>
<property name="maximumSize"> <property name="defaultDropAction">
<size> <enum>Qt::IgnoreAction</enum>
<width>130</width>
<height>16777215</height>
</size>
</property>
<property name="alternatingRowColors">
<bool>false</bool>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property> </property>
<property name="textElideMode"> <property name="textElideMode">
<enum>Qt::ElideMiddle</enum> <enum>Qt::ElideRight</enum>
</property> </property>
<property name="movement"> <property name="movement">
<enum>QListView::Static</enum> <enum>QListView::Static</enum>
@ -148,12 +127,6 @@
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
</property> </property>
<property name="gridSize">
<size>
<width>100</width>
<height>26</height>
</size>
</property>
<property name="viewMode"> <property name="viewMode">
<enum>QListView::ListMode</enum> <enum>QListView::ListMode</enum>
</property> </property>
@ -191,21 +164,12 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>666</width> <width>540</width>
<height>517</height> <height>495</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin"> <property name="margin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number> <number>3</number>
</property> </property>
<item> <item>

View File

@ -25,7 +25,6 @@ public:
virtual void getValues(std::map<std::string,float>& values) const; virtual void getValues(std::map<std::string,float>& values) const;
virtual QString displayValue(float v) const; virtual QString displayValue(float v) const;
// virtual QString displayName(int i) const;
virtual QString legend(int i,float v) const; virtual QString legend(int i,float v) const;
virtual void update(); virtual void update();
QString unitName() const ; QString unitName() const ;

View File

@ -23,6 +23,8 @@ BandwidthStatsWidget::BandwidthStatsWidget(QWidget *parent)
ui.unit_CB->addItem(tr("KB/s")) ; ui.unit_CB->addItem(tr("KB/s")) ;
ui.unit_CB->addItem(tr("Count")) ; ui.unit_CB->addItem(tr("Count")) ;
ui.logScale_CB->setChecked(true) ;
ui.bwgraph_BW->source()->setSelector(BWGraphSource::SELECTOR_TYPE_FRIEND,BWGraphSource::GRAPH_TYPE_SUM) ; ui.bwgraph_BW->source()->setSelector(BWGraphSource::SELECTOR_TYPE_FRIEND,BWGraphSource::GRAPH_TYPE_SUM) ;
ui.bwgraph_BW->source()->setSelector(BWGraphSource::SELECTOR_TYPE_SERVICE,BWGraphSource::GRAPH_TYPE_SUM) ; ui.bwgraph_BW->source()->setSelector(BWGraphSource::SELECTOR_TYPE_SERVICE,BWGraphSource::GRAPH_TYPE_SUM) ;
ui.bwgraph_BW->source()->setUnit(BWGraphSource::UNIT_KILOBYTES) ; ui.bwgraph_BW->source()->setUnit(BWGraphSource::UNIT_KILOBYTES) ;
@ -33,6 +35,7 @@ BandwidthStatsWidget::BandwidthStatsWidget(QWidget *parent)
QObject::connect(ui.updn_CB ,SIGNAL(currentIndexChanged(int)),this, SLOT( updateUpDownSelection(int))) ; QObject::connect(ui.updn_CB ,SIGNAL(currentIndexChanged(int)),this, SLOT( updateUpDownSelection(int))) ;
QObject::connect(ui.unit_CB ,SIGNAL(currentIndexChanged(int)),this, SLOT( updateUnitSelection(int))) ; QObject::connect(ui.unit_CB ,SIGNAL(currentIndexChanged(int)),this, SLOT( updateUnitSelection(int))) ;
QObject::connect(ui.service_CB,SIGNAL(currentIndexChanged(int)),this, SLOT(updateServiceSelection(int))) ; QObject::connect(ui.service_CB,SIGNAL(currentIndexChanged(int)),this, SLOT(updateServiceSelection(int))) ;
QObject::connect(ui.logScale_CB,SIGNAL(toggled(bool)),this, SLOT(toggleLogScale(bool))) ;
// setup one timer for auto-update // setup one timer for auto-update
@ -42,6 +45,13 @@ BandwidthStatsWidget::BandwidthStatsWidget(QWidget *parent)
mTimer->start(2000) ; mTimer->start(2000) ;
} }
void BandwidthStatsWidget::toggleLogScale(bool b)
{
if(b)
ui.bwgraph_BW->setFlags(RSGraphWidget::RSGRAPH_FLAGS_LOG_SCALE_Y) ;
else
ui.bwgraph_BW->resetFlags(RSGraphWidget::RSGRAPH_FLAGS_LOG_SCALE_Y) ;
}
void BandwidthStatsWidget::updateComboBoxes() void BandwidthStatsWidget::updateComboBoxes()
{ {
if(!isVisible()) if(!isVisible())

View File

@ -14,6 +14,7 @@ protected slots:
void updateComboBoxes() ; void updateComboBoxes() ;
void updateUpDownSelection(int n); void updateUpDownSelection(int n);
void updateUnitSelection(int n); void updateUnitSelection(int n);
void toggleLogScale(bool b);
private: private:
Ui::BwStatsWidget ui; Ui::BwStatsWidget ui;

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>812</width> <width>1128</width>
<height>349</height> <height>385</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -18,14 +18,7 @@
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
<widget class="BWGraph" name="bwgraph_BW"> <widget class="BWGraph" name="bwgraph_BW" native="true"/>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="informationSelector_GB"> <widget class="QGroupBox" name="informationSelector_GB">
@ -110,6 +103,13 @@
<item> <item>
<widget class="QComboBox" name="unit_CB"/> <widget class="QComboBox" name="unit_CB"/>
</item> </item>
<item>
<widget class="QCheckBox" name="logScale_CB">
<property name="text">
<string>Log scale</string>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
@ -131,8 +131,8 @@
<customwidgets> <customwidgets>
<customwidget> <customwidget>
<class>BWGraph</class> <class>BWGraph</class>
<extends>QFrame</extends> <extends>QWidget</extends>
<header>gui/statistics/BWGraph.h</header> <header location="global">gui/statistics/BWGraph.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
</customwidgets> </customwidgets>

View File

@ -23,6 +23,7 @@
#include <QTimer> #include <QTimer>
#include <QObject> #include <QObject>
#include <QFontMetrics> #include <QFontMetrics>
#include <QWheelEvent>
#include <time.h> #include <time.h>
#include <QMenu> #include <QMenu>
@ -52,7 +53,7 @@
#define COL_RECEIVED 7 #define COL_RECEIVED 7
#define COL_SEND 8 #define COL_SEND 8
static const int PARTIAL_VIEW_SIZE = 5 ;
static const int MAX_TUNNEL_REQUESTS_DISPLAY = 10 ; static const int MAX_TUNNEL_REQUESTS_DISPLAY = 10 ;
static QColor colorScale(float f) static QColor colorScale(float f)
@ -211,6 +212,7 @@ GlobalRouterStatisticsWidget::GlobalRouterStatisticsWidget(QWidget *parent)
maxWidth = 400*fact ; maxWidth = 400*fact ;
maxHeight = 0 ; maxHeight = 0 ;
mCurrentN = PARTIAL_VIEW_SIZE/2+1 ;
} }
void GlobalRouterStatisticsWidget::updateContent() void GlobalRouterStatisticsWidget::updateContent()
@ -219,6 +221,8 @@ void GlobalRouterStatisticsWidget::updateContent()
rsGRouter->getRoutingMatrixInfo(matrix_info) ; rsGRouter->getRoutingMatrixInfo(matrix_info) ;
mNumberOfKnownKeys = matrix_info.per_friend_probabilities.size() ;
float size = QFontMetricsF(font()).height() ; float size = QFontMetricsF(font()).height() ;
float fact = size/14.0 ; float fact = size/14.0 ;
@ -302,44 +306,85 @@ void GlobalRouterStatisticsWidget::updateContent()
oy += celly ; oy += celly ;
oy += celly ; oy += celly ;
//print friends in the same order their prob is shown // //print friends in the same order their prob is shown
QString FO = tr("Friend Order ("); // QString FO = tr("Friend Order (");
RsPeerDetails peer_ssl_details; // RsPeerDetails peer_ssl_details;
for(uint32_t i=0;i<matrix_info.friend_ids.size();++i){ // for(uint32_t i=0;i<matrix_info.friend_ids.size();++i){
rsPeers->getPeerDetails(matrix_info.friend_ids[i], peer_ssl_details); // rsPeers->getPeerDetails(matrix_info.friend_ids[i], peer_ssl_details);
QString fn = QString::fromUtf8(peer_ssl_details.name.c_str()); // QString fn = QString::fromUtf8(peer_ssl_details.name.c_str());
FO+=fn; // FO+=fn;
FO+=" "; // FO+=" ";
//
} // }
FO+=")"; // FO+=")";
//
painter.drawText(ox+0*cellx,oy+fm_times.height(),FO) ; // painter.drawText(ox+0*cellx,oy+fm_times.height(),FO) ;
oy += celly ; // oy += celly ;
oy += celly ; // oy += celly ;
static const int MaxKeySize = 20*fact ; static const int MaxKeySize = 20*fact ;
painter.setFont(monospace_f) ; painter.setFont(monospace_f) ;
for(std::map<GRouterKeyId,std::vector<float> >::const_iterator it(matrix_info.per_friend_probabilities.begin());it!=matrix_info.per_friend_probabilities.end();++it) int n=0;
{ QString ids;
bool is_null = true ; std::vector<float> current_probs ;
int current_oy = 0 ;
for(uint32_t i=0;i<matrix_info.friend_ids.size();++i) mMinWheelZoneX = ox+2*cellx ;
if(it->second[i] > 0.0) mMinWheelZoneY = oy ;
is_null = false ;
if(!is_null) for(std::map<GRouterKeyId,std::vector<float> >::const_iterator it(matrix_info.per_friend_probabilities.begin());it!=matrix_info.per_friend_probabilities.end();++it,++n)
if(n >= mCurrentN-PARTIAL_VIEW_SIZE/2 && n <= mCurrentN+PARTIAL_VIEW_SIZE/2)
{ {
QString ids = QString::fromStdString(it->first.toStdString())+" : " ; //bool is_null = false ;
//for(uint32_t i=0;i<matrix_info.friend_ids.size();++i)
// if(it->second[i] > 0.0)
// is_null = false ;
//if(!is_null)
//{
ids = QString::fromStdString(it->first.toStdString())+" : " ;
mMaxWheelZoneX = ox+2*cellx + fm_monospace.width(ids);
painter.drawText(ox+2*cellx,oy+celly,ids) ; painter.drawText(ox+2*cellx,oy+celly,ids) ;
for(uint32_t i=0;i<matrix_info.friend_ids.size();++i) for(uint32_t i=0;i<matrix_info.friend_ids.size();++i)
painter.fillRect(ox+i*cellx+fm_monospace.width(ids),oy,cellx,celly,colorScale(it->second[i])) ; painter.fillRect(ox+i*cellx+fm_monospace.width(ids),oy+0.15*celly,cellx,celly,colorScale(it->second[i])) ;
if(n == mCurrentN)
{
current_probs = it->second ;
current_oy = oy ;
}
oy += celly ; oy += celly ;
//}
} }
mMaxWheelZoneY = oy+celly ;
painter.setPen(QColor::fromRgb(0,0,0)) ;
painter.setPen(QColor::fromRgb(0.5,0.5,0.5));
painter.drawRect(ox+2*cellx,current_oy+0.15*celly,fm_monospace.width(ids)+cellx*matrix_info.friend_ids.size()- 2*cellx,celly) ;
float total_length = (matrix_info.friend_ids.size()+2)*cellx ;
if(!current_probs.empty())
for(uint32_t i=0;i<matrix_info.friend_ids.size();++i)
{
float x1 = ox+(i+0.5)*cellx+fm_monospace.width(ids) ;
float y1 = oy+0.15*celly ;
float y2 = y1+(matrix_info.friend_ids.size()-1-i+1)*celly;
RsPeerDetails peer_ssl_details;
rsPeers->getPeerDetails(matrix_info.friend_ids[i], peer_ssl_details);
painter.drawLine(x1,y1,x1,y2);
painter.drawLine(x1,y2,x1 + total_length - i*cellx,y2) ;
painter.drawText(cellx+ x1 + total_length - i*cellx,y2+(0.35)*celly, QString::fromUtf8(peer_ssl_details.name.c_str()) + " ("+QString::number(current_probs[i])+")");
} }
oy += celly * (2+matrix_info.friend_ids.size());
oy += celly ; oy += celly ;
oy += celly ; oy += celly ;
@ -350,6 +395,24 @@ void GlobalRouterStatisticsWidget::updateContent()
maxHeight = oy ; maxHeight = oy ;
} }
void GlobalRouterStatisticsWidget::wheelEvent(QWheelEvent *e)
{
if(e->x() < mMinWheelZoneX || e->x() > mMaxWheelZoneX || e->y() < mMinWheelZoneY || e->y() > mMaxWheelZoneY)
{
QWidget::wheelEvent(e) ;
return ;
}
if(e->delta() > 0 && mCurrentN+PARTIAL_VIEW_SIZE/2+1 < mNumberOfKnownKeys)
mCurrentN++ ;
if(e->delta() < 0 && mCurrentN > PARTIAL_VIEW_SIZE/2+1)
mCurrentN-- ;
updateContent();
update();
}
QString GlobalRouterStatisticsWidget::speedString(float f) QString GlobalRouterStatisticsWidget::speedString(float f)
{ {
if(f < 1.0f) if(f < 1.0f)

View File

@ -68,6 +68,7 @@ class GlobalRouterStatisticsWidget: public QWidget
virtual void paintEvent(QPaintEvent *event) ; virtual void paintEvent(QPaintEvent *event) ;
virtual void resizeEvent(QResizeEvent *event); virtual void resizeEvent(QResizeEvent *event);
virtual void wheelEvent(QWheelEvent *event);
void updateContent() ; void updateContent() ;
private: private:
@ -75,5 +76,11 @@ class GlobalRouterStatisticsWidget: public QWidget
QPixmap pixmap ; QPixmap pixmap ;
int maxWidth,maxHeight ; int maxWidth,maxHeight ;
int mCurrentN ;
int mNumberOfKnownKeys ;
int mMinWheelZoneX ;
int mMinWheelZoneY ;
int mMaxWheelZoneX ;
int mMaxWheelZoneY ;
}; };

View File

@ -25,9 +25,9 @@
#include "SysTrayStatus.h" #include "SysTrayStatus.h"
#define IMAGE_NOONLINE ":/images/logo/logo_24_0.png" #define IMAGE_NOONLINE ":/icons/logo_0_connected_128.png"
#define IMAGE_ONEONLINE ":/images/logo/logo_24_1.png" #define IMAGE_ONEONLINE ":/icons/logo_1_connected_128.png"
#define IMAGE_TWOONLINE ":/images/logo/logo_24_2.png" #define IMAGE_TWOONLINE ":/icons/logo_2_connected_128.png"
SysTrayStatus::SysTrayStatus(QWidget *parent) : SysTrayStatus::SysTrayStatus(QWidget *parent) :
QWidget(parent) QWidget(parent)
@ -40,7 +40,6 @@ SysTrayStatus::SysTrayStatus(QWidget *parent) :
imageButton->setIcon(QIcon(IMAGE_NOONLINE)); imageButton->setIcon(QIcon(IMAGE_NOONLINE));
imageButton->setFlat(true); imageButton->setFlat(true);
imageButton->setCheckable(false); imageButton->setCheckable(false);
imageButton->setMaximumSize(24, 24);
imageButton->setFocusPolicy(Qt::ClickFocus); imageButton->setFocusPolicy(Qt::ClickFocus);
hbox->addWidget(imageButton); hbox->addWidget(imageButton);

View File

@ -36,9 +36,12 @@ ToasterDisable::ToasterDisable(QWidget *parent)
hbox->setSpacing(0); hbox->setSpacing(0);
imageButton = new QPushButton(this); imageButton = new QPushButton(this);
int S = QFontMetricsF(imageButton->font()).height();
imageButton->setFlat(true); imageButton->setFlat(true);
imageButton->setCheckable(true); imageButton->setCheckable(true);
imageButton->setMaximumSize(24, 24); imageButton->setMaximumSize(S,S);
imageButton->setFocusPolicy(Qt::ClickFocus); imageButton->setFocusPolicy(Qt::ClickFocus);
hbox->addWidget(imageButton); hbox->addWidget(imageButton);
@ -55,7 +58,7 @@ ToasterDisable::ToasterDisable(QWidget *parent)
void ToasterDisable::disable(bool isDisable) void ToasterDisable::disable(bool isDisable)
{ {
imageButton->setIcon(QIcon(isDisable ? IMAGE_TOASTERDISABLE : IMAGE_TOASTERENABLE)); imageButton->setIcon(QPixmap(isDisable ? IMAGE_TOASTERDISABLE : IMAGE_TOASTERENABLE));
imageButton->setToolTip(isDisable ? tr("All Toasters are disabled") : tr("Toasters are enabled")); imageButton->setToolTip(isDisable ? tr("All Toasters are disabled") : tr("Toasters are enabled"));
imageButton->setChecked(isDisable); imageButton->setChecked(isDisable);
} }

View File

@ -40,10 +40,13 @@ DHTStatus::DHTStatus(QWidget *parent)
hbox->setSpacing(6); hbox->setSpacing(6);
statusDHT = new QLabel("<strong>" + tr("DHT") + ":</strong>", this ); statusDHT = new QLabel("<strong>" + tr("DHT") + ":</strong>", this );
statusDHT->setToolTip(tr("<p>Retroshare uses Bittorrent's DHT as a proxy for connexions. It does not \"store\" your IP in the DHT. \
Instead the DHT is used by your friends to reach you while processing standard DHT requests. \
The status bullet will turn green as soon as Retroshare gets a DHT response from one of your friends.</p>")) ;
hbox->addWidget(statusDHT); hbox->addWidget(statusDHT);
dhtstatusLabel = new QLabel( this ); dhtstatusLabel = new QLabel( this );
dhtstatusLabel->setPixmap(QPixmap(":/images/grayled.png")); dhtstatusLabel->setPixmap(QPixmap(":/icons/bullet_grey_128.png"));
hbox->addWidget(dhtstatusLabel); hbox->addWidget(dhtstatusLabel);
spaceLabel = new QLabel( "|", this ); spaceLabel = new QLabel( "|", this );
@ -52,7 +55,8 @@ DHTStatus::DHTStatus(QWidget *parent)
dhtnetworkLabel = new QLabel( this ); dhtnetworkLabel = new QLabel( this );
dhtnetworkLabel->setVisible(false); dhtnetworkLabel->setVisible(false);
dhtnetworkLabel->setPixmap(QPixmap(":/images/dht16.png")); int S = QFontMetricsF(dhtnetworkLabel->font()).height();
dhtnetworkLabel->setPixmap(QPixmap(":/images/dht32.png").scaledToHeight(S,Qt::SmoothTransformation));
hbox->addWidget(dhtnetworkLabel); hbox->addWidget(dhtnetworkLabel);
dhtnetworksizeLabel = new QLabel( "0 (0) ",this ); dhtnetworksizeLabel = new QLabel( "0 (0) ",this );
@ -125,7 +129,7 @@ void DHTStatus::getDHTStatus()
{ {
// RED - some issue. // RED - some issue.
dhtstatusLabel->setPixmap(QPixmap(":/icons/bullet_red_128.png").scaledToHeight(S,Qt::SmoothTransformation)); dhtstatusLabel->setPixmap(QPixmap(":/icons/bullet_red_128.png").scaledToHeight(S,Qt::SmoothTransformation));
dhtstatusLabel->setToolTip( text + tr("DHT Error")); dhtstatusLabel->setToolTip( text + tr("No peer found in DHT"));
spaceLabel->setVisible(false); spaceLabel->setVisible(false);
dhtnetworkLabel->setVisible(false); dhtnetworkLabel->setVisible(false);

View File

@ -31,13 +31,13 @@ PeerStatus::PeerStatus(QWidget *parent)
hbox->setMargin(0); hbox->setMargin(0);
hbox->setSpacing(6); hbox->setSpacing(6);
iconLabel = new QLabel( this ); iconLabel = new QLabel( this );
iconLabel->setPixmap(QPixmap(":/images/user/identitygray16.png")); int S = QFontMetricsF(iconLabel->font()).height();
// iconLabel doesn't change over time, so we didn't need a minimum size iconLabel->setPixmap(QPixmap(":/icons/avatar_grey_128.png").scaledToHeight(S,Qt::SmoothTransformation));
hbox->addWidget(iconLabel); hbox->addWidget(iconLabel);
statusPeers = new QLabel( tr("Friends: 0/0"), this ); statusPeers = new QLabel( tr("Friends: 0/0"), this );
// statusPeers->setMinimumSize( statusPeers->frameSize().width() + 0, 0 );
hbox->addWidget(statusPeers); hbox->addWidget(statusPeers);
_compactMode = false; _compactMode = false;
@ -57,13 +57,10 @@ void PeerStatus::getPeerStatus(unsigned int nFriendCount, unsigned int nOnlineCo
else text = QString("<strong>%1:</strong> %2/%3 ").arg(tr("Friends")).arg(nOnlineCount).arg(nFriendCount); else text = QString("<strong>%1:</strong> %2/%3 ").arg(tr("Friends")).arg(nOnlineCount).arg(nFriendCount);
statusPeers -> setText(text); statusPeers -> setText(text);
} }
int S = QFontMetricsF(iconLabel->font()).height();
if (nOnlineCount > 0) if (nOnlineCount > 0)
{ iconLabel->setPixmap(QPixmap(":/icons/avatar_128.png").scaledToHeight(S,Qt::SmoothTransformation));
iconLabel->setPixmap(QPixmap(":/images/user/identity16.png"));
}
else else
{ iconLabel->setPixmap(QPixmap(":/icons/avatar_grey_128.png").scaledToHeight(S,Qt::SmoothTransformation));
iconLabel->setPixmap(QPixmap(":/images/user/identitygray16.png"));
}
} }

View File

@ -25,7 +25,7 @@
#include <rshare.h> #include <rshare.h>
#include "gui/MainWindow.h" #include "gui/MainWindow.h"
#include "gui/FriendsDialog.h" #include "gui/FriendsDialog.h"
#include "gui/SearchDialog.h" #include "gui/FileTransfer/SearchDialog.h"
#include "gui/FileTransfer/TransfersDialog.h" #include "gui/FileTransfer/TransfersDialog.h"
#include "gui/SharedFilesDialog.h" #include "gui/SharedFilesDialog.h"
#include "gui/NetworkDialog.h" #include "gui/NetworkDialog.h"

View File

@ -320,7 +320,6 @@ HEADERS += rshare.h \
gui/RemoteDirModel.h \ gui/RemoteDirModel.h \
gui/RetroShareLink.h \ gui/RetroShareLink.h \
gui/SearchTreeWidget.h \ gui/SearchTreeWidget.h \
gui/SearchDialog.h \
gui/SharedFilesDialog.h \ gui/SharedFilesDialog.h \
gui/ShareManager.h \ gui/ShareManager.h \
gui/ShareDialog.h \ gui/ShareDialog.h \
@ -329,6 +328,7 @@ HEADERS += rshare.h \
gui/HelpDialog.h \ gui/HelpDialog.h \
gui/LogoBar.h \ gui/LogoBar.h \
gui/common/AvatarDialog.h \ gui/common/AvatarDialog.h \
gui/FileTransfer/SearchDialog.h \
gui/FileTransfer/xprogressbar.h \ gui/FileTransfer/xprogressbar.h \
gui/FileTransfer/DetailsDialog.h \ gui/FileTransfer/DetailsDialog.h \
gui/FileTransfer/FileTransferInfoWidget.h \ gui/FileTransfer/FileTransferInfoWidget.h \
@ -558,11 +558,11 @@ FORMS += gui/StartDialog.ui \
gui/common/AvatarDialog.ui \ gui/common/AvatarDialog.ui \
gui/FileTransfer/TransfersDialog.ui \ gui/FileTransfer/TransfersDialog.ui \
gui/FileTransfer/DetailsDialog.ui \ gui/FileTransfer/DetailsDialog.ui \
gui/FileTransfer/SearchDialog.ui \
gui/MainWindow.ui \ gui/MainWindow.ui \
gui/NetworkView.ui \ gui/NetworkView.ui \
gui/MessengerWindow.ui \ gui/MessengerWindow.ui \
gui/FriendsDialog.ui \ gui/FriendsDialog.ui \
gui/SearchDialog.ui \
gui/SharedFilesDialog.ui \ gui/SharedFilesDialog.ui \
gui/ShareManager.ui \ gui/ShareManager.ui \
gui/ShareDialog.ui \ gui/ShareDialog.ui \
@ -682,7 +682,6 @@ SOURCES += main.cpp \
gui/RsAutoUpdatePage.cpp \ gui/RsAutoUpdatePage.cpp \
gui/RetroShareLink.cpp \ gui/RetroShareLink.cpp \
gui/SearchTreeWidget.cpp \ gui/SearchTreeWidget.cpp \
gui/SearchDialog.cpp \
gui/SharedFilesDialog.cpp \ gui/SharedFilesDialog.cpp \
gui/ShareManager.cpp \ gui/ShareManager.cpp \
gui/ShareDialog.cpp \ gui/ShareDialog.cpp \
@ -694,6 +693,7 @@ SOURCES += main.cpp \
gui/im_history/IMHistoryItemPainter.cpp \ gui/im_history/IMHistoryItemPainter.cpp \
gui/help/browser/helpbrowser.cpp \ gui/help/browser/helpbrowser.cpp \
gui/help/browser/helptextbrowser.cpp \ gui/help/browser/helptextbrowser.cpp \
gui/FileTransfer/SearchDialog.cpp \
gui/FileTransfer/TransfersDialog.cpp \ gui/FileTransfer/TransfersDialog.cpp \
gui/FileTransfer/FileTransferInfoWidget.cpp \ gui/FileTransfer/FileTransferInfoWidget.cpp \
gui/FileTransfer/DLListDelegate.cpp \ gui/FileTransfer/DLListDelegate.cpp \

View File

@ -30,6 +30,7 @@
class UserNotify; class UserNotify;
class QAbstractButton ; class QAbstractButton ;
class FloatingHelpBrowser; class FloatingHelpBrowser;
class QToolButton;
class MainPage : public QWidget class MainPage : public QWidget
{ {
@ -60,7 +61,7 @@ public:
// Overload this to add some help info to the page. The way the info is // Overload this to add some help info to the page. The way the info is
// shown is handled by showHelp() below; // shown is handled by showHelp() below;
// //
void registerHelpButton(QAbstractButton *button, const QString& help_html_text) ; void registerHelpButton(QToolButton *button, const QString& help_html_text) ;
private: private:
FloatingHelpBrowser *mHelpBrowser ; FloatingHelpBrowser *mHelpBrowser ;

View File

@ -1067,6 +1067,7 @@ QString RsHtml::makeQuotedText(RSTextBrowser *browser)
} }
QStringList sl = text.split(QRegExp("[\r\n]"),QString::SkipEmptyParts); QStringList sl = text.split(QRegExp("[\r\n]"),QString::SkipEmptyParts);
text = sl.join("\n>"); text = sl.join("\n>");
text.replace(QChar(-4),"");//Char used when image on text.
return QString(">") + text; return QString(">") + text;
} }