Merge pull request #842 from csoler/v0.6-GxsTransport

V0.6 gxs transport
This commit is contained in:
csoler 2017-05-26 22:04:33 +02:00 committed by GitHub
commit 7c439983de
57 changed files with 2226 additions and 613 deletions

View File

@ -266,7 +266,7 @@ libs/curl-$(CURL_VERSION): $(DOWNLOAD_PATH)/curl-$(CURL_VERSION).tar.gz
sqlcipher: libs/sqlcipher-$(SQLCIPHER_VERSION)
$(DOWNLOAD_PATH)/tcl$(TCL_VERSION)-src.tar.gz:
wget http://prdownloads.sourceforge.net/tcl/tcl$(TCL_VERSION)-src.tar.gz -O $(DOWNLOAD_PATH)/tcl$(TCL_VERSION)-src.tar.gz
wget --no-check-certificate http://downloads.sourceforge.net/project/tcl/Tcl/$(TCL_VERSION)/tcl$(TCL_VERSION)-src.tar.gz -O $(DOWNLOAD_PATH)/tcl$(TCL_VERSION)-src.tar.gz
$(DOWNLOAD_PATH)/sqlcipher-$(SQLCIPHER_VERSION).tar.gz:
wget --no-check-certificate https://github.com/sqlcipher/sqlcipher/archive/v$(SQLCIPHER_VERSION).tar.gz -O $(DOWNLOAD_PATH)/sqlcipher-$(SQLCIPHER_VERSION).tar.gz

View File

@ -1624,11 +1624,18 @@ Sha1CheckSum p3GRouter::computeDataItemHash(RsGRouterGenericDataItem *data_item)
RsTemporaryMemory mem(total_size) ;
uint32_t offset = 0 ;
signature_serializer.serialise(data_item,mem,&total_size) ;
offset += signed_data_size ;
uint32_t tmp_size = total_size ;
signature_serializer.serialise(data_item,mem,&tmp_size) ;
if(tmp_size != signed_data_size)
std::cerr << "(EE) Some error occured in p3GRouter::computeDataItemHash(). Mismatched offset/data size" << std::endl;
offset += tmp_size ;
data_item->signature.SetTlv(mem, total_size,&offset) ;
if(offset != total_size)
std::cerr << "(EE) Some error occured in p3GRouter::computeDataItemHash(). Mismatched offset/data size" << std::endl;
return RsDirUtil::sha1sum(mem,total_size) ;
}

View File

@ -1576,11 +1576,20 @@ bool RsGxsDataAccess::getGroupStatistic(GroupStatisticRequest *req)
req->mGroupStatistic.mNumChildMsgsNew = 0;
req->mGroupStatistic.mNumChildMsgsUnread = 0;
std::set<RsGxsMessageId> obsolete_msgs ; // stored message ids that are referred to as older versions of an existing message
for(uint32_t i = 0; i < msgMetaV.size(); ++i)
if(!msgMetaV[i]->mOrigMsgId.isNull() && msgMetaV[i]->mOrigMsgId!=msgMetaV[i]->mMsgId)
obsolete_msgs.insert(msgMetaV[i]->mOrigMsgId);
for(uint32_t i = 0; i < msgMetaV.size(); ++i)
{
RsGxsMsgMetaData* m = msgMetaV[i];
req->mGroupStatistic.mTotalSizeOfMsgs += m->mMsgSize + m->serial_size();
if(obsolete_msgs.find(m->mMsgId) != obsolete_msgs.end()) // skip obsolete messages.
continue;
if (IS_MSG_NEW(m->mMsgStatus))
{
if (m->mParentId.isNull())

View File

@ -16,11 +16,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "util/rsdir.h"
#include "gxstrans/p3gxstrans.h"
#include "util/stacktrace.h"
typedef unsigned int uint;
RsGxsTrans *rsGxsTrans = NULL ;
p3GxsTrans::~p3GxsTrans()
{
p3Config::saveConfiguration();
@ -31,6 +34,35 @@ p3GxsTrans::~p3GxsTrans()
}
}
bool p3GxsTrans::getStatistics(GxsTransStatistics& stats)
{
stats.prefered_group_id = mPreferredGroupId;
stats.outgoing_records.clear();
{
RS_STACK_MUTEX(mOutgoingMutex);
for ( auto it = mOutgoingQueue.begin(); it != mOutgoingQueue.end(); ++it)
{
const OutgoingRecord& pr(it->second);
RsGxsTransOutgoingRecord rec ;
rec.status = pr.status ;
rec.send_TS = pr.mailItem.meta.mPublishTs ;
rec.group_id = pr.mailItem.meta.mGroupId ;
rec.trans_id = pr.mailItem.mailId ;
rec.recipient = pr.recipient ;
rec.data_size = pr.mailData.size();
rec.data_hash = RsDirUtil::sha1sum(pr.mailData.data(),pr.mailData.size());
rec.client_service = pr.clientService ;
stats.outgoing_records.push_back(rec) ;
}
}
return true;
}
bool p3GxsTrans::sendMail( RsGxsTransId& mailId,
GxsTransSubServices service,
const RsGxsId& own_gxsid, const RsGxsId& recipient,
@ -120,9 +152,9 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
&& meta.mGroupId != mPreferredGroupId;
if(shoudlSubscribe)
subscribeToGroup(token, meta.mGroupId, true);
RsGenExchange::subscribeToGroup(token, meta.mGroupId, true);
else if(shoudlUnSubscribe)
subscribeToGroup(token, meta.mGroupId, false);
RsGenExchange::subscribeToGroup(token, meta.mGroupId, false);
#ifdef GXS_MAIL_GRP_DEBUG
char buff[30];
@ -337,7 +369,7 @@ void p3GxsTrans::notifyChanges(std::vector<RsGxsNotify*>& changes)
std::cout << "p3GxsTrans::notifyChanges(...) msgChange" << std::endl;
uint32_t token;
RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
getTokenService()->requestMsgInfo( token, 0xcaca,
RsGenExchange::getTokenService()->requestMsgInfo( token, 0xcaca,
opts, msgChange->msgChangeMap );
GxsTokenQueue::queueRequest(token, MAILS_UPDATE);
@ -393,8 +425,8 @@ bool p3GxsTrans::requestGroupsData(const std::list<RsGxsGroupId>* groupIds)
// std::cout << "p3GxsTrans::requestGroupsList()" << std::endl;
uint32_t token;
RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
if(!groupIds) getTokenService()->requestGroupInfo(token, 0xcaca, opts);
else getTokenService()->requestGroupInfo(token, 0xcaca, opts, *groupIds);
if(!groupIds) RsGenExchange::getTokenService()->requestGroupInfo(token, 0xcaca, opts);
else RsGenExchange::getTokenService()->requestGroupInfo(token, 0xcaca, opts, *groupIds);
GxsTokenQueue::queueRequest(token, GROUPS_LIST);
return true;
}

View File

@ -26,6 +26,7 @@
#include "gxstrans/p3gxstransitems.h"
#include "services/p3idservice.h" // For p3IdService
#include "util/rsthreads.h"
#include "retroshare/rsgxstrans.h"
struct p3GxsTrans;
@ -76,18 +77,32 @@ struct GxsTransClient
* @see GxsTransClient::receiveGxsTransMail(...),
* @see GxsTransClient::notifyGxsTransSendStatus(...).
*/
struct p3GxsTrans : RsGenExchange, GxsTokenQueue, p3Config
class p3GxsTrans : public RsGenExchange, public GxsTokenQueue, public p3Config, public RsGxsTrans
{
public:
p3GxsTrans( RsGeneralDataService* gds, RsNetworkExchangeService* nes,
p3IdService& identities ) :
RsGenExchange( gds, nes, new RsGxsTransSerializer(),
RS_SERVICE_TYPE_GXS_TRANS, &identities,
AuthenPolicy(), GXS_STORAGE_PERIOD ),
GxsTokenQueue(this), mIdService(identities),
GxsTokenQueue(this),
RsGxsTrans(this),
mIdService(identities),
mServClientsMutex("p3GxsTrans client services map mutex"),
mOutgoingMutex("p3GxsTrans outgoing queue map mutex"),
mIngoingMutex("p3GxsTrans ingoing queue map mutex") {}
~p3GxsTrans();
virtual ~p3GxsTrans();
/*!
* \brief getStatistics
* Gathers all sorts of statistics about the internals of p3GxsTrans, in order to display info about the running status,
* message transport, etc.
* \param stats This structure contains all statistics information.
* \return true is the call succeeds.
*/
virtual bool getStatistics(GxsTransStatistics& stats);
/**
* Send an email to recipient, in the process author of the email is

View File

@ -23,30 +23,11 @@
#include "serialiser/rsbaseserial.h"
#include "serialiser/rstlvidset.h"
#include "retroshare/rsgxsflags.h"
#include "retroshare/rsgxstrans.h"
#include "retroshare/rsgxscircles.h" // For: GXS_CIRCLE_TYPE_PUBLIC
#include "services/p3idservice.h"
#include "serialiser/rstypeserializer.h"
/// Subservices identifiers (like port for TCP)
enum class GxsTransSubServices : uint16_t
{
UNKNOWN = 0,
TEST_SERVICE = 1,
P3_MSG_SERVICE = 2,
P3_CHAT_SERVICE = 3
};
/// Values must fit into uint8_t
enum class GxsTransItemsSubtypes : uint8_t
{
GXS_TRANS_SUBTYPE_MAIL = 1,
GXS_TRANS_SUBTYPE_RECEIPT = 2,
GXS_TRANS_SUBTYPE_GROUP = 3,
OUTGOING_RECORD_ITEM = 4
};
typedef uint64_t RsGxsTransId;
struct RsNxsTransPresignedReceipt : RsNxsMsg
{
RsNxsTransPresignedReceipt() : RsNxsMsg(RS_SERVICE_TYPE_GXS_TRANS) {}
@ -188,27 +169,6 @@ struct RsGxsTransGroupItem : RsGxsGrpItem
{ return out; }
};
enum class GxsTransSendStatus : uint8_t
{
UNKNOWN = 0,
PENDING_PROCESSING,
PENDING_PREFERRED_GROUP,
PENDING_RECEIPT_CREATE,
PENDING_RECEIPT_SIGNATURE,
PENDING_SERIALIZATION,
PENDING_PAYLOAD_CREATE,
PENDING_PAYLOAD_ENCRYPT,
PENDING_PUBLISH,
/** This will be useful so the user can know if the mail reached at least
* some friend node, in case of internet connection interruption */
//PENDING_TRANSFER,
PENDING_RECEIPT_RECEIVE,
/// Records with status >= RECEIPT_RECEIVED get deleted
RECEIPT_RECEIVED,
FAILED_RECEIPT_SIGNATURE = 240,
FAILED_ENCRYPTION
};
class RsGxsTransSerializer;
struct OutgoingRecord : RsItem
{

View File

@ -60,6 +60,8 @@ public:
public:
RsMsgMetaData mMeta;
std::set<RsGxsMessageId> mOlderVersions ;
std::string mMsg; // UTF8 encoded.
std::list<RsGxsFile> mFiles;

View File

@ -0,0 +1,103 @@
#pragma once
#include "retroshare/rstokenservice.h"
#include "retroshare/rsgxsifacehelper.h"
#include "retroshare/rsgxscommon.h"
/// Subservices identifiers (like port for TCP)
enum class GxsTransSubServices : uint16_t
{
UNKNOWN = 0x00,
TEST_SERVICE = 0x01,
P3_MSG_SERVICE = 0x02,
P3_CHAT_SERVICE = 0x03
};
/// Values must fit into uint8_t
enum class GxsTransItemsSubtypes : uint8_t
{
GXS_TRANS_SUBTYPE_MAIL = 0x01,
GXS_TRANS_SUBTYPE_RECEIPT = 0x02,
GXS_TRANS_SUBTYPE_GROUP = 0x03,
OUTGOING_RECORD_ITEM = 0x04
};
enum class GxsTransSendStatus : uint8_t
{
UNKNOWN = 0x00,
PENDING_PROCESSING = 0x01,
PENDING_PREFERRED_GROUP = 0x02,
PENDING_RECEIPT_CREATE = 0x03,
PENDING_RECEIPT_SIGNATURE = 0x04,
PENDING_SERIALIZATION = 0x05,
PENDING_PAYLOAD_CREATE = 0x06,
PENDING_PAYLOAD_ENCRYPT = 0x07,
PENDING_PUBLISH = 0x08,
/** This will be useful so the user can know if the mail reached at least
* some friend node, in case of internet connection interruption */
//PENDING_TRANSFER,
PENDING_RECEIPT_RECEIVE = 0x09,
/// Records with status >= RECEIPT_RECEIVED get deleted
RECEIPT_RECEIVED = 0x0a,
FAILED_RECEIPT_SIGNATURE = 0xf0,
FAILED_ENCRYPTION = 0xf1
};
typedef uint64_t RsGxsTransId;
class RsGxsTransGroup
{
public:
RsGroupMetaData mMeta;
};
class RsGxsTransMsg
{
public:
RsGxsTransMsg() : size(0),data(NULL) {}
virtual ~RsGxsTransMsg() { free(data) ; }
public:
RsMsgMetaData mMeta;
uint32_t size ;
uint8_t *data ;
};
struct RsGxsTransOutgoingRecord
{
GxsTransSendStatus status;
RsGxsId recipient;
RsGxsTransId trans_id;
GxsTransSubServices client_service;
uint32_t data_size ;
Sha1CheckSum data_hash ;
uint32_t send_TS ;
RsGxsGroupId group_id ;
};
class RsGxsTrans: public RsGxsIfaceHelper
{
public:
class GxsTransStatistics
{
public:
GxsTransStatistics() {}
RsGxsGroupId prefered_group_id ;
std::vector<RsGxsTransOutgoingRecord> outgoing_records;
};
RsGxsTrans(RsGxsIface *gxs) : RsGxsIfaceHelper(gxs) {}
virtual ~RsGxsTrans() {}
virtual bool getStatistics(GxsTransStatistics& stats)=0;
// virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsTransGroup> &groups) = 0;
// virtual bool getPostData(const uint32_t &token, std::vector<RsGxsTransMsg> &posts) = 0;
};
extern RsGxsTrans *rsGxsTrans ;

View File

@ -1799,6 +1799,8 @@ int RsServer::StartupRetroShare()
rsPosted = mPosted;
rsGxsForums = mGxsForums;
rsGxsChannels = mGxsChannels;
rsGxsTrans = mGxsTrans;
//rsPhoto = mPhoto;
//rsWire = mWire;

View File

@ -161,12 +161,12 @@ GenCertDialog::GenCertDialog(bool onlyGenerateIdentity, QWidget *parent)
ui.keylength_comboBox->addItem("Very high (4096 bits)", QVariant(4096));
#if QT_VERSION >= 0x040700
ui.node_input->setPlaceholderText(tr("[Required] Examples: Home, Laptop,...(Visible to friends).")) ;
ui.hiddenaddr_input->setPlaceholderText(tr("[Optional] Tor/I2P address (Example: xa76giaf6ifda7ri63i263.onion)")) ;
ui.name_input->setPlaceholderText(tr("[Required] Visible to friends, and friends of friends."));
ui.nickname_input->setPlaceholderText(tr("[Optional] Used to write in chat rooms and forums. Can be set later."));
ui.password_input->setPlaceholderText(tr("[Required] This password protects your data. Dont forget it!"));
ui.password_input_2->setPlaceholderText(tr("[Required] Type the same password again here."));
ui.node_input->setPlaceholderText(tr("Node name")) ;
ui.hiddenaddr_input->setPlaceholderText(tr("Tor/I2P address")) ;
ui.name_input->setPlaceholderText(tr("Username"));
ui.nickname_input->setPlaceholderText(tr("Identity name"));
ui.password_input->setPlaceholderText(tr("Password"));
ui.password_input_2->setPlaceholderText(tr("Password again"));
#endif
ui.nickname_input->setMaxLength(RSID_MAXIMUM_NICKNAME_SIZE);
@ -294,7 +294,7 @@ void GenCertDialog::setupState()
ui.entropy_bar->setVisible(true);
ui.genButton->setVisible(true);
ui.genButton->setText(generate_new?tr("Generate new profile and node"):tr("Generate new node"));
ui.genButton->setText(generate_new?tr("Generate"):tr("Generate"));
ui.hiddenaddr_input->setVisible(hidden_state);
ui.hiddenaddr_label->setVisible(hidden_state);

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>533</width>
<height>544</height>
<width>520</width>
<height>611</height>
</rect>
</property>
<property name="windowTitle">
@ -34,13 +34,16 @@
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame">
<widget class="QFrame" name="profileframe">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
@ -48,6 +51,9 @@
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>9</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
@ -105,19 +111,63 @@
</layout>
</item>
<item>
<widget class="QFrame" name="profile_frame">
<widget class="QGroupBox" name="profile_groupBox">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>24</number>
</property>
<property name="topMargin">
<number>24</number>
</property>
<property name="rightMargin">
<number>24</number>
</property>
<property name="bottomMargin">
<number>24</number>
</property>
<item row="0" column="0">
<layout class="QGridLayout" name="profilGLayout">
<item row="14" column="2">
<widget class="QComboBox" name="keylength_comboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>PGP Key Length</string>
</property>
<property name="accessibleDescription">
<string/>
</property>
</widget>
</item>
<item row="18" column="1">
<widget class="QLabel" name="randomness_label_">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/randomness.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="7" column="3">
<widget class="QLabel" name="password_check_LB">
<property name="text">
@ -125,17 +175,7 @@
</property>
</widget>
</item>
<item row="15" column="0">
<widget class="QLabel" name="keylength_label">
<property name="text">
<string>PGP key length</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="9" column="2">
<item row="8" column="2">
<widget class="QLineEdit" name="password_input_2">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
@ -163,42 +203,6 @@
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="password_label">
<property name="toolTip">
<string>This password is for PGP</string>
</property>
<property name="text">
<string>Password</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="15" column="2">
<widget class="QComboBox" name="keylength_comboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="password_label_2">
<property name="toolTip">
<string>This password is for PGP</string>
</property>
<property name="text">
<string>Password (check)</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="18" column="2">
<widget class="QProgressBar" name="entropy_bar">
<property name="sizePolicy">
@ -229,7 +233,7 @@
</property>
</widget>
</item>
<item row="16" column="2">
<item row="15" column="2">
<widget class="QComboBox" name="nodeType_CB">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -271,16 +275,6 @@
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="node_label">
<property name="text">
<string>Node name</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QLabel" name="profile_name_check_LB">
<property name="text">
@ -365,7 +359,7 @@
</item>
</layout>
</item>
<item row="9" column="3">
<item row="8" column="3">
<widget class="QLabel" name="password2_check_LB">
<property name="text">
<string/>
@ -394,46 +388,6 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="name_label">
<property name="text">
<string>Profile name</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="18" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Randomness</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="16" column="0">
<widget class="QLabel" name="label_nodeType">
<property name="text">
<string>Node type</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="17" column="0">
<widget class="QLabel" name="hiddenaddr_label">
<property name="text">
<string>hidden address</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="17" column="2">
<layout class="QHBoxLayout" name="hiddenInfoHLayout">
<property name="spacing">
@ -498,20 +452,7 @@
</item>
</layout>
</item>
<item row="10" column="0">
<widget class="QLabel" name="nickname_label">
<property name="toolTip">
<string/>
</property>
<property name="text">
<string>Chat identity</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="10" column="2">
<item row="9" column="2">
<widget class="QLineEdit" name="nickname_input">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -564,6 +505,191 @@
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="name_label">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/person.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLabel" name="nickname_label">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/chat-lobbies.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="node_label">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/network.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QLabel" name="keylength_label">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/keyring.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="password_label_2">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>This password is for PGP</string>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/password.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="password_label">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>This password is for PGP</string>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/password.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="17" column="1">
<widget class="QLabel" name="hiddenaddr_label">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/hidden.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="15" column="1">
<widget class="QLabel" name="label_nodeType">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/netgraph.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>

View File

@ -1403,7 +1403,7 @@ void NewsFeed::openChat(const RsPeerId &peerId)
ChatDialog::chatFriend(ChatId(peerId));
}
void NewsFeed::openComments(uint32_t /*type*/, const RsGxsGroupId &/*groupId*/, const RsGxsMessageId &/*msgId*/, const QString &/*title*/)
void NewsFeed::openComments(uint32_t /*type*/, const RsGxsGroupId &/*groupId*/, const QVector<RsGxsMessageId>& versions,const RsGxsMessageId &/*msgId*/, const QString &/*title*/)
{
std::cerr << "NewsFeed::openComments() Not Handled Yet";
std::cerr << std::endl;

View File

@ -58,7 +58,7 @@ public:
virtual QScrollArea *getScrollArea();
virtual void deleteFeedItem(QWidget *item, uint32_t type);
virtual void openChat(const RsPeerId& peerId);
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, const QString &title);
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &versions, const RsGxsMessageId &msgId, const QString &title);
static void testFeeds(uint notifyFlags);
static void testFeed(FeedNotify *feedNotify);

View File

@ -411,7 +411,13 @@ void PostedItem::loadComments()
if (mFeedHolder)
{
QString title = QString::fromUtf8(mPost.mMeta.mMsgName.c_str());
mFeedHolder->openComments(0, mPost.mMeta.mGroupId, mPost.mMeta.mMsgId, title);
#warning (csoler) Posted item versions not handled yet. When it is the case, start here.
QVector<RsGxsMessageId> post_versions ;
post_versions.push_back(mPost.mMeta.mMsgId) ;
mFeedHolder->openComments(0, mPost.mMeta.mGroupId, post_versions,mPost.mMeta.mMsgId, title);
}
}

View File

@ -139,9 +139,9 @@ void PostedListWidget::openChat(const RsPeerId & /*peerId*/)
return;
}
void PostedListWidget::openComments(uint32_t /*feed_type*/, const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, const QString &title)
void PostedListWidget::openComments(uint32_t /*feed_type*/, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &versions, const RsGxsMessageId &msgId, const QString &title)
{
emit loadComment(groupId, msgId, title);
emit loadComment(groupId, versions,msgId, title);
}
void PostedListWidget::newPost()

View File

@ -52,7 +52,7 @@ public:
virtual QScrollArea *getScrollArea();
virtual void deleteFeedItem(QWidget *item, uint32_t type);
virtual void openChat(const RsPeerId& peerId);
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, const QString &title);
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &versions, const RsGxsMessageId &msgId, const QString &title);
/* GXS functions */
virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req);

View File

@ -17,6 +17,9 @@
<iconset resource="images.qrc">
<normaloff>:/images/logo/logo_32.png</normaloff>:/images/logo/logo_32.png</iconset>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
@ -31,296 +34,310 @@
<number>0</number>
</property>
<item>
<layout class="QGridLayout" name="mainGLayout">
<property name="leftMargin">
<number>0</number>
<widget class="QFrame" name="loginframe">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="rightMargin">
<number>0</number>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="bottomMargin">
<number>0</number>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<item row="0" column="0" colspan="4">
<layout class="QGridLayout" name="topGLayout">
<item row="0" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QLabel" name="rsTopLogo">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>85</red>
<green>170</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>85</red>
<green>170</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>118</red>
<green>116</green>
<blue>108</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="font">
<font>
<pointsize>18</pointsize>
</font>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="images.qrc">:/images/logo/logo_spash2.png</pixmap>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>48</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="2" rowspan="2">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>60</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0" colspan="3">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" rowspan="2">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>60</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<widget class="QGroupBox" name="profilGBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin">
<number>9</number>
</property>
<layout class="QGridLayout" name="mainGLayout">
<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>
<item row="0" column="0" colspan="4">
<layout class="QGridLayout" name="topGLayout">
<item row="0" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Profile - Location:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_9">
<property name="maximumSize">
<widget class="QLabel" name="rsTopLogo">
<property name="minimumSize">
<size>
<width>22</width>
<height>22</height>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>85</red>
<green>170</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>85</red>
<green>170</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>118</red>
<green>116</green>
<blue>108</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/person.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="loadName"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_11">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/password.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="password_input">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
<property name="placeholderText">
<string>Password</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="autologin_checkbox">
<property name="text">
<string>Remember Password</string>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="loadButton">
<property name="font">
<font>
<pointsize>12</pointsize>
<pointsize>18</pointsize>
</font>
</property>
<property name="text">
<string>Log In</string>
<string/>
</property>
<property name="default">
<bool>true</bool>
</property>
<property name="flat">
<bool>false</bool>
<property name="pixmap">
<pixmap resource="images.qrc">:/images/logo/logo_spash2.png</pixmap>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>48</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</item>
<item row="1" column="2" rowspan="2">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>60</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0" colspan="3">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" rowspan="2">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>60</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<widget class="QGroupBox" name="profilGBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin">
<number>9</number>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="labelProfile">
<property name="toolTip">
<string>Opens a dialog for creating a new profile or
<item row="0" column="1">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Profile - Location:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_9">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/person.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="loadName"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_11">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="icons.qrc">:/icons/svg/password.svg</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="password_input">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
<property name="placeholderText">
<string>Password</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="autologin_checkbox">
<property name="text">
<string>Remember Password</string>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="loadButton">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Log In</string>
</property>
<property name="default">
<bool>true</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="labelProfile">
<property name="toolTip">
<string>Opens a dialog for creating a new profile or
adding locations to an existing profile.
The current identities/locations will not be affected.</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;Create new Profile...&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;Manage profiles and nodes...&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>

View File

@ -1429,7 +1429,8 @@ void ChatWidget::colorChanged()
void ChatWidget::chooseFont()
{
bool ok;
QFont font = QFontDialog::getFont(&ok, currentFont, this);
//Use NULL as parent as with this QFontDialog don't take care of title nether options.
QFont font = QFontDialog::getFont(&ok, currentFont, NULL, tr("Choose your font."),QFontDialog::DontUseNativeDialog);
if (ok) {
currentFont = font;
setFont();

View File

@ -37,7 +37,7 @@ public:
virtual QScrollArea *getScrollArea() = 0;
virtual void deleteFeedItem(QWidget *item, uint32_t type) = 0;
virtual void openChat(const RsPeerId& peerId) = 0;
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, const QString &title) = 0;
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &msg_versions, const RsGxsMessageId &msgId, const QString &title)=0;
// Workaround for QTBUG-3372
void lockLayout(QWidget *feedItem, bool lock);

View File

@ -35,6 +35,7 @@
#include "util/HandleRichText.h"
#include "util/DateTime.h"
#include "util/stringutil.h"
#include "gui/gxschannels/CreateGxsChannelMsg.h"
#include <iostream>
@ -63,9 +64,25 @@ GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId,
std::cerr << std::endl;
#endif
QVector<RsGxsMessageId> v;
bool self = false;
for(std::set<RsGxsMessageId>::const_iterator it(post.mOlderVersions.begin());it!=post.mOlderVersions.end();++it)
{
if(*it == post.mMeta.mMsgId)
self = true ;
v.push_back(*it) ;
}
if(!self)
v.push_back(post.mMeta.mMsgId);
setMessageVersions(v) ;
setup();
setGroup(group, false);
//setGroup(group, false);
requestGroup();
setPost(post);
requestComment();
}
@ -127,6 +144,7 @@ void GxsChannelPostItem::setup()
connect(ui->commentButton, SIGNAL(clicked()), this, SLOT(loadComments()));
connect(ui->playButton, SIGNAL(clicked()), this, SLOT(play(void)));
connect(ui->editButton, SIGNAL(clicked()), this, SLOT(edit(void)));
connect(ui->copyLinkButton, SIGNAL(clicked()), this, SLOT(copyMessageLink()));
connect(ui->readButton, SIGNAL(toggled(bool)), this, SLOT(readToggled(bool)));
@ -166,6 +184,12 @@ bool GxsChannelPostItem::setGroup(const RsGxsChannelGroup &group, bool doFill)
mGroup = group;
// if not publisher, hide the edit button. Without the publish key, there's no way to edit a message.
std::cerr << "Group subscribe flags = " << std::hex << mGroup.mMeta.mSubscribeFlags << std::dec << std::endl;
if(!IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags))
ui->editButton->hide();
if (doFill) {
fill();
}
@ -301,7 +325,7 @@ void GxsChannelPostItem::loadComment(const uint32_t &token)
if (comNb == 1) {
sComButText = sComButText.append("(1)");
} else if (comNb > 1) {
sComButText = tr("Comments").append("(%1)").arg(comNb);
sComButText = tr("Comments ").append("(%1)").arg(comNb);
}
ui->commentButton->setText(sComButText);
}
@ -690,6 +714,12 @@ void GxsChannelPostItem::download()
updateItem();
}
void GxsChannelPostItem::edit()
{
CreateGxsChannelMsg *msgDialog = new CreateGxsChannelMsg(mGroup.mMeta.mGroupId,mPost.mMeta.mMsgId);
msgDialog->show();
}
void GxsChannelPostItem::play()
{
std::list<SubFileItem *>::iterator it;

View File

@ -78,6 +78,7 @@ private slots:
void readAndClearItem();
void download();
void play();
void edit();
void loadComments();
void readToggled(bool checked);

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>840</width>
<height>180</height>
<width>1052</width>
<height>338</height>
</rect>
</property>
<layout class="QGridLayout" name="gxsChannelPostItem_GLayout">
@ -332,6 +332,13 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="editButton">
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">

View File

@ -97,11 +97,12 @@ SubFileItem::SubFileItem(const RsFileHash &hash, const std::string &name, const
void SubFileItem::Setup()
{
connect( playButton, SIGNAL( clicked( void ) ), this, SLOT( play ( void ) ) );
connect( downloadButton, SIGNAL( clicked( void ) ), this, SLOT( download ( void ) ) );
connect( cancelButton, SIGNAL( clicked( void ) ), this, SLOT( cancel ( void ) ) );
connect( copyLinkButton, SIGNAL( clicked( void ) ), this, SLOT( copyLink ( void ) ) );
connect( saveButton, SIGNAL( clicked( void ) ), this, SLOT( save ( void ) ) );
connect( playButton, SIGNAL( clicked( ) ), this, SLOT( play ( ) ) );
connect( downloadButton, SIGNAL( clicked( ) ), this, SLOT( download ( ) ) );
connect( cancelButton, SIGNAL( clicked( ) ), this, SLOT( cancel( ) ) );
connect( deleteButton, SIGNAL( clicked( ) ), this, SLOT( del( ) ) );
connect( copyLinkButton, SIGNAL( clicked( ) ), this, SLOT( copyLink ( ) ) );
connect( saveButton, SIGNAL( clicked( ) ), this, SLOT( save ( ) ) );
/* once off check - if remote, check if we have it
* NB: This check might be expensive - and it'll happen often!
@ -129,12 +130,21 @@ void SubFileItem::Setup()
}
}
deleteButton->setVisible(mFlag & SFI_FLAG_ALLOW_DELETE);
downloadButton->setVisible(mMode < SFI_STATE_LOCAL);
cancelButton->setVisible(mMode < SFI_STATE_LOCAL);
smaller();
updateItemStatic();
updateItem();
}
void SubFileItem::del()
{
emit wantsToBeDeleted();
}
bool SubFileItem::done()
{
return (mMode >= SFI_STATE_LOCAL);
@ -176,7 +186,7 @@ void SubFileItem::updateItemStatic()
}
/* get full path for local file */
if ((mMode == SFI_STATE_LOCAL) || (mMode == SFI_STATE_UPLOAD))
if (((mMode == SFI_STATE_LOCAL) || (mMode == SFI_STATE_UPLOAD)))
{
#ifdef DEBUG_ITEM
std::cerr << "SubFileItem::updateItemStatic() STATE=Local/Upload checking path";
@ -190,7 +200,10 @@ void SubFileItem::updateItemStatic()
/* look up path */
if (!rsFiles->FileDetails(mFileHash, hintflags, fi))
{
mMode = SFI_STATE_ERROR;
if(mFlag & SFI_FLAG_ASSUME_FILE_READY)
mMode = SFI_STATE_REMOTE;
else
mMode = SFI_STATE_ERROR;
#ifdef DEBUG_ITEM
std::cerr << "SubFileItem::updateItemStatic() STATE=>Error No Details";
std::cerr << std::endl;
@ -241,6 +254,7 @@ void SubFileItem::updateItemStatic()
case SFI_STATE_REMOTE:
playButton->setEnabled(false);
downloadButton->setEnabled(true);
downloadButton->setVisible(true);
cancelButton->setEnabled(false);
progressBar->setValue(0);

View File

@ -40,7 +40,9 @@ const uint32_t SFI_STATE_UPLOAD = 0x0006;
const uint32_t SFI_TYPE_CHANNEL = 0x0010;
const uint32_t SFI_TYPE_ATTACH = 0x0020;
const uint32_t SFI_FLAG_CREATE = 0x1000;
const uint32_t SFI_FLAG_CREATE = 0x1000;
const uint32_t SFI_FLAG_ALLOW_DELETE = 0x2000;
const uint32_t SFI_FLAG_ASSUME_FILE_READY = 0x4000;
//! This create a gui widget that allows users to access files shared by user
@ -86,10 +88,14 @@ private slots:
void toggle();
void cancel();
void del();
void save();
void updateItem();
signals:
void wantsToBeDeleted();
private:
void Setup();

View File

@ -6,12 +6,21 @@
<rect>
<x>0</x>
<y>0</y>
<width>464</width>
<height>71</height>
<width>547</width>
<height>128</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<property name="margin">
<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="spacing">
@ -26,27 +35,6 @@
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="fileLabel">
<property name="font">
<font>
<weight>75</weight>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text">
<string notr="true">File Name</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
@ -210,6 +198,41 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="deleteButton">
<property name="toolTip">
<string>Remove this item</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/denied16.png</normaloff>:/images/denied16.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="fileLabel">
<property name="font">
<font>
<weight>75</weight>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text">
<string notr="true">File Name</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>

View File

@ -54,7 +54,7 @@ void GxsCommentContainer::setup()
ui.tabWidget->hideCloseButton(index);
}
void GxsCommentContainer::commentLoad(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId, const QString &title)
void GxsCommentContainer::commentLoad(const RsGxsGroupId &grpId, const std::set<RsGxsMessageId>& msg_versions,const RsGxsMessageId &msgId, const QString &title)
{
QString comments = title;
if (title.length() > MAX_COMMENT_TITLE)
@ -68,7 +68,7 @@ void GxsCommentContainer::commentLoad(const RsGxsGroupId &grpId, const RsGxsMess
QWidget *commentHeader = createHeaderWidget(grpId, msgId);
commentDialog->setCommentHeader(commentHeader);
commentDialog->commentLoad(grpId, msgId);
commentDialog->commentLoad(grpId, msg_versions, msgId);
ui.tabWidget->addTab(commentDialog, comments);
}

View File

@ -40,7 +40,7 @@ public:
GxsCommentContainer(QWidget *parent = 0);
void setup();
void commentLoad(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId, const QString &title);
void commentLoad(const RsGxsGroupId &grpId, const std::set<RsGxsMessageId> &msg_versions, const RsGxsMessageId &msgId, const QString &title);
virtual GxsServiceDialog *createServiceDialog() = 0;
virtual QString getServiceName() = 0;
@ -67,9 +67,9 @@ public:
virtual ~GxsServiceDialog() { return; }
void commentLoad(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId, const QString &title)
void commentLoad(const RsGxsGroupId &grpId, const std::set<RsGxsMessageId>& msg_versions,const RsGxsMessageId &msgId, const QString &title)
{
mContainer->commentLoad(grpId, msgId, title);
mContainer->commentLoad(grpId, msg_versions,msgId, title);
}
private:

View File

@ -59,20 +59,16 @@ GxsCommentDialog::~GxsCommentDialog()
delete(ui);
}
void GxsCommentDialog::commentLoad(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId)
void GxsCommentDialog::commentLoad(const RsGxsGroupId &grpId, const std::set<RsGxsMessageId>& msg_versions,const RsGxsMessageId& most_recent_msgId)
{
std::cerr << "GxsCommentDialog::commentLoad(" << grpId << ", " << msgId << ")";
std::cerr << "GxsCommentDialog::commentLoad(" << grpId << ", most recent msg version: " << most_recent_msgId << ")";
std::cerr << std::endl;
mGrpId = grpId;
mMsgId = msgId;
mMostRecentMsgId = most_recent_msgId;
mMsgVersions = msg_versions;
RsGxsGrpMsgIdPair threadId;
threadId.first = grpId;
threadId.second = msgId;
ui->treeWidget->requestComments(threadId);
ui->treeWidget->requestComments(mGrpId,msg_versions,most_recent_msgId);
}
void GxsCommentDialog::refresh()
@ -80,7 +76,7 @@ void GxsCommentDialog::refresh()
std::cerr << "GxsCommentDialog::refresh()";
std::cerr << std::endl;
commentLoad(mGrpId, mMsgId);
commentLoad(mGrpId, mMsgVersions,mMostRecentMsgId);
}
void GxsCommentDialog::idChooserReady()

View File

@ -39,10 +39,10 @@ public:
virtual ~GxsCommentDialog();
void setCommentHeader(QWidget *header);
void commentLoad(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId);
void commentLoad(const RsGxsGroupId &grpId, const std::set<RsGxsMessageId> &msg_versions, const RsGxsMessageId &most_recent_msgId);
RsGxsGroupId groupId() { return mGrpId; }
RsGxsMessageId messageId() { return mMsgId; }
RsGxsMessageId messageId() { return mMostRecentMsgId; }
private slots:
void refresh();
@ -51,7 +51,8 @@ private slots:
private:
RsGxsGroupId mGrpId;
RsGxsMessageId mMsgId;
RsGxsMessageId mMostRecentMsgId;
std::set<RsGxsMessageId> mMsgVersions;
/* UI - from Designer */
Ui::GxsCommentDialog *ui;

View File

@ -22,8 +22,12 @@
*/
#include <QMimeData>
#include <QTextDocument>
#include <QAbstractTextDocumentLayout>
#include <QApplication>
#include <QDateTime>
#include <QMenu>
#include <QPainter>
#include "gui/common/RSElidedItemDelegate.h"
#include "gui/gxs/GxsCommentTreeWidget.h"
@ -46,11 +50,73 @@
#define COMMENT_VOTE_ACK 0x001234
#define POST_CELL_SIZE_ROLE (Qt::UserRole+1)
#define POST_COLOR_ROLE (Qt::UserRole+2)
/* Images for context menu icons */
#define IMAGE_MESSAGE ":/images/folder-draft.png"
#define IMAGE_VOTEUP ":/images/vote_up.png"
#define IMAGE_VOTEDOWN ":/images/vote_down.png"
#define IMAGE_VOTEUP ":/images/vote_up.png"
#define IMAGE_VOTEDOWN ":/images/vote_down.png"
// This class allows to draw the item using an appropriate size
class MultiLinesCommentDelegate: public QStyledItemDelegate
{
public:
MultiLinesCommentDelegate(QFontMetricsF f) : qf(f){}
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return index.data(POST_CELL_SIZE_ROLE).toSize() ;
}
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_ASSERT(index.isValid());
QStyleOptionViewItemV4 opt = option;
initStyleOption(&opt, index);
// disable default icon
opt.icon = QIcon();
opt.text = QString();
// draw default item
QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, 0);
const QRect r = option.rect;
QTextDocument td ;
td.setHtml("<html>"+index.data(Qt::DisplayRole).toString()+"</html>");
QSizeF s = td.documentLayout()->documentSize();
int m = QFontMetricsF(QFont()).height();
QSize full_area(std::min(r.width(),(int)s.width())+m,std::min(r.height(),(int)s.height())+m);
QPixmap px(full_area.width(),full_area.height());
px.fill();
QPainter p(&px) ;
p.setRenderHint(QPainter::Antialiasing);
QPainterPath path ;
path.addRoundedRect(QRectF(m/4.0,m/4.0,s.width()+m/2.0,s.height()+m/2.0),m,m) ;
QPen pen(Qt::gray,m/7.0f);
p.setPen(pen);
p.fillPath(path,QColor::fromHsv( index.data(POST_COLOR_ROLE).toInt()/255.0*360,40,220)); // varies the color according to the post author
p.drawPath(path);
QAbstractTextDocumentLayout::PaintContext ctx;
ctx.clip = QRectF(0,0,s.width(),s.height());
p.translate(QPointF(m/2.0,m/2.0));
td.documentLayout()->draw( &p, ctx );
painter->drawPixmap(r.topLeft(),px);
const_cast<QAbstractItemModel*>(index.model())->setData(index,px.size(),POST_CELL_SIZE_ROLE);
}
private:
QFontMetricsF qf;
};
GxsCommentTreeWidget::GxsCommentTreeWidget(QWidget *parent)
:QTreeWidget(parent), mTokenQueue(NULL), mRsTokenService(NULL), mCommentService(NULL)
@ -62,6 +128,9 @@ GxsCommentTreeWidget::GxsCommentTreeWidget(QWidget *parent)
itemDelegate->setSpacing(QSize(0, 2));
setItemDelegate(itemDelegate);
setWordWrap(true);
setItemDelegateForColumn(PCITEM_COLUMN_COMMENT,new MultiLinesCommentDelegate(QFontMetricsF(font()))) ;
// QFont font = QFont("ARIAL", 10);
// font.setBold(true);
@ -85,14 +154,14 @@ GxsCommentTreeWidget::~GxsCommentTreeWidget()
}
}
void GxsCommentTreeWidget::setCurrentMsgId(QTreeWidgetItem *current, QTreeWidgetItem *previous)
void GxsCommentTreeWidget::setCurrentCommentMsgId(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
Q_UNUSED(previous);
if(current)
{
mCurrentMsgId = RsGxsMessageId(current->text(PCITEM_COLUMN_MSGID).toStdString());
mCurrentCommentMsgId = RsGxsMessageId(current->text(PCITEM_COLUMN_MSGID).toStdString());
}
}
@ -100,9 +169,9 @@ void GxsCommentTreeWidget::customPopUpMenu(const QPoint& /*point*/)
{
QMenu contextMnu( this );
QAction* action = contextMnu.addAction(QIcon(IMAGE_MESSAGE), tr("Reply to Comment"), this, SLOT(replyToComment()));
action->setDisabled(mCurrentMsgId.isNull());
action->setDisabled(mCurrentCommentMsgId.isNull());
action = contextMnu.addAction(QIcon(IMAGE_MESSAGE), tr("Submit Comment"), this, SLOT(makeComment()));
action->setDisabled(mThreadId.first.isNull());
action->setDisabled(mMsgVersions.empty());
contextMnu.addSeparator();
@ -112,7 +181,7 @@ void GxsCommentTreeWidget::customPopUpMenu(const QPoint& /*point*/)
action->setDisabled(mVoterId.isNull());
if (!mCurrentMsgId.isNull())
if (!mCurrentCommentMsgId.isNull())
{
// not implemented yet
/*
@ -138,7 +207,8 @@ void GxsCommentTreeWidget::voteUp()
{
std::cerr << "GxsCommentTreeWidget::voteUp()";
std::cerr << std::endl;
vote(mThreadId.first, mThreadId.second, mCurrentMsgId, mVoterId, true);
vote(mGroupId, mLatestMsgId, mCurrentCommentMsgId, mVoterId, true);
}
@ -146,7 +216,8 @@ void GxsCommentTreeWidget::voteDown()
{
std::cerr << "GxsCommentTreeWidget::voteDown()";
std::cerr << std::endl;
vote(mThreadId.first, mThreadId.second, mCurrentMsgId, mVoterId, false);
vote(mGroupId, mLatestMsgId, mCurrentCommentMsgId, mVoterId, false);
}
void GxsCommentTreeWidget::setVoteId(const RsGxsId &voterId)
@ -216,16 +287,16 @@ void GxsCommentTreeWidget::banUser()
void GxsCommentTreeWidget::makeComment()
{
GxsCreateCommentDialog pcc(mTokenQueue, mCommentService, mThreadId, mThreadId.second, this);
GxsCreateCommentDialog pcc(mTokenQueue, mCommentService, std::make_pair(mGroupId,mLatestMsgId), mLatestMsgId, this);
pcc.exec();
}
void GxsCommentTreeWidget::replyToComment()
{
RsGxsGrpMsgIdPair msgId;
msgId.first = mThreadId.first;
msgId.second = mCurrentMsgId;
GxsCreateCommentDialog pcc(mTokenQueue, mCommentService, msgId, mThreadId.second, this);
msgId.first = mGroupId;
msgId.second = mCurrentCommentMsgId;
GxsCreateCommentDialog pcc(mTokenQueue, mCommentService, msgId, mLatestMsgId, this);
pcc.exec();
}
@ -235,36 +306,44 @@ void GxsCommentTreeWidget::setup(RsTokenService *token_service, RsGxsCommentServ
mCommentService = comment_service;
mTokenQueue = new TokenQueue(token_service, this);
connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customPopUpMenu(QPoint)));
connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(setCurrentMsgId(QTreeWidgetItem*, QTreeWidgetItem*)));
connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(setCurrentCommentMsgId(QTreeWidgetItem*, QTreeWidgetItem*)));
return;
}
/* Load Comments */
void GxsCommentTreeWidget::requestComments(const RsGxsGrpMsgIdPair& threadId)
void GxsCommentTreeWidget::requestComments(const RsGxsGroupId& group, const std::set<RsGxsMessageId>& message_versions,const RsGxsMessageId& most_recent_message)
{
/* request comments */
mThreadId = threadId;
service_requestComments(threadId);
mGroupId = group ;
mMsgVersions = message_versions ;
mLatestMsgId = most_recent_message;
service_requestComments(group,message_versions);
}
void GxsCommentTreeWidget::service_requestComments(const RsGxsGrpMsgIdPair& threadId)
void GxsCommentTreeWidget::service_requestComments(const RsGxsGroupId& group_id,const std::set<RsGxsMessageId> & msgIds)
{
/* request comments */
std::cerr << "GxsCommentTreeWidget::service_requestComments(" << threadId.second << ")";
std::cerr << std::endl;
std::cerr << "GxsCommentTreeWidget::service_requestComments for group " << group_id << std::endl;
std::vector<RsGxsGrpMsgIdPair> ids_to_ask;
for(std::set<RsGxsMessageId>::const_iterator it(msgIds.begin());it!=msgIds.end();++it)
{
std::cerr << " asking for msg " << *it << std::endl;
ids_to_ask.push_back(std::make_pair(group_id,*it));
}
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA;
opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST;
std::vector<RsGxsGrpMsgIdPair> msgIds;
msgIds.push_back(threadId);
uint32_t token;
mTokenQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, GXSCOMMENTS_LOADTHREAD);
mTokenQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, ids_to_ask, GXSCOMMENTS_LOADTHREAD);
}
@ -317,7 +396,7 @@ void GxsCommentTreeWidget::completeItems()
parent->addChild(pit->second);
}
else if (parentId == mThreadId.second)
else if (mMsgVersions.find(parentId) != mMsgVersions.end())
{
std::cerr << "GxsCommentTreeWidget::completeItems() Added to topLevelItems";
std::cerr << std::endl;
@ -391,7 +470,7 @@ void GxsCommentTreeWidget::acknowledgeComment(const uint32_t &token)
mCommentService->acknowledgeComment(token, msgId);
// simply reload data
service_requestComments(mThreadId);
service_requestComments(mGroupId,mMsgVersions);
}
@ -401,7 +480,7 @@ void GxsCommentTreeWidget::acknowledgeVote(const uint32_t &token)
if (mCommentService->acknowledgeVote(token, msgId))
{
// reload data if vote was added.
service_requestComments(mThreadId);
service_requestComments(mGroupId,mMsgVersions);
}
}
@ -441,6 +520,7 @@ void GxsCommentTreeWidget::service_loadThread(const uint32_t &token)
RsGxsId authorId = comment.mMeta.mAuthorId;
item->setId(authorId, PCITEM_COLUMN_AUTHOR, false);
item->setData(PCITEM_COLUMN_COMMENT,POST_COLOR_ROLE,QVariant(authorId.toByteArray()[1]));
text = QString::number(comment.mScore);
item->setText(PCITEM_COLUMN_SCORE, text);

View File

@ -39,7 +39,7 @@ public:
~GxsCommentTreeWidget();
void setup(RsTokenService *token_service, RsGxsCommentService *comment_service);
void requestComments(const RsGxsGrpMsgIdPair& threadId);
void requestComments(const RsGxsGroupId& group, const std::set<RsGxsMessageId> &message_versions, const RsGxsMessageId &most_recent_message);
void getCurrentMsgId(RsGxsMessageId& parentId);
void applyRankings(std::map<RsGxsMessageId, uint32_t>& positions);
@ -49,7 +49,7 @@ public:
protected:
/* to be overloaded */
virtual void service_requestComments(const RsGxsGrpMsgIdPair& threadId);
virtual void service_requestComments(const RsGxsGroupId &group_id, const std::set<RsGxsMessageId> &msgIds);
virtual void service_loadThread(const uint32_t &token);
virtual QTreeWidgetItem *service_createMissingItem(const RsGxsMessageId& parent);
@ -65,7 +65,7 @@ protected:
public slots:
void customPopUpMenu(const QPoint& point);
void setCurrentMsgId(QTreeWidgetItem* current, QTreeWidgetItem* previous);
void setCurrentCommentMsgId(QTreeWidgetItem* current, QTreeWidgetItem* previous);
void makeComment();
@ -85,8 +85,10 @@ protected:
const RsGxsMessageId &parentId, const RsGxsId &authorId, bool up);
/* Data */
RsGxsGrpMsgIdPair mThreadId;
RsGxsMessageId mCurrentMsgId;
RsGxsGroupId mGroupId;
std::set<RsGxsMessageId> mMsgVersions;
RsGxsMessageId mLatestMsgId;
RsGxsMessageId mCurrentCommentMsgId;
RsGxsId mVoterId;
std::map<RsGxsMessageId, QTreeWidgetItem *> mLoadingMap;

View File

@ -64,7 +64,10 @@ void GxsFeedItem::comments(const QString &title)
if (mFeedHolder)
{
mFeedHolder->openComments(feedId(), groupId(), messageId(), title);
if(mMessageVersions.empty())
mFeedHolder->openComments(feedId(), groupId(),QVector<RsGxsMessageId>(1,messageId()), messageId(), title);
else
mFeedHolder->openComments(feedId(), groupId(),mMessageVersions, messageId(), title);
}
}
@ -153,12 +156,12 @@ void GxsFeedItem::requestComment()
opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA;
opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST;
RsGxsGrpMsgIdPair msgIdPair;
msgIdPair.first = groupId();
msgIdPair.second = messageId();
std::vector<RsGxsGrpMsgIdPair> msgIds;
msgIds.push_back(msgIdPair);
for(uint32_t i=0;i<mMessageVersions.size();++i)
msgIds.push_back(std::make_pair(groupId(),mMessageVersions[i]));
msgIds.push_back(std::make_pair(groupId(),messageId()));
uint32_t token;
mLoadQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeComment);

View File

@ -35,9 +35,12 @@ public:
GxsFeedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, RsGxsIfaceHelper *iface, bool autoUpdate);
virtual ~GxsFeedItem();
RsGxsMessageId messageId() { return mMessageId; }
RsGxsMessageId messageId() const { return mMessageId; }
const QVector<RsGxsMessageId>& messageVersions() const { return mMessageVersions ; }
//To be able to update with thread message when comment is received.
void setMessageId( RsGxsMessageId id) {mMessageId = id;}
void setMessageVersions( const QVector<RsGxsMessageId>& v) { mMessageVersions = v;}
protected:
/* load message data */
@ -61,6 +64,7 @@ protected slots:
private:
RsGxsMessageId mMessageId;
QVector<RsGxsMessageId> mMessageVersions ;
uint32_t mTokenTypeMessage;
uint32_t mTokenTypeComment;
};

View File

@ -45,8 +45,8 @@ public:
GxsGroupFeedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, RsGxsIfaceHelper *iface, bool autoUpdate);
virtual ~GxsGroupFeedItem();
RsGxsGroupId groupId() { return mGroupId; }
uint32_t feedId() { return mFeedId; }
RsGxsGroupId groupId() const { return mGroupId; }
uint32_t feedId() const { return mFeedId; }
protected:
uint32_t nextTokenType() { return ++mNextTokenType; }

View File

@ -525,7 +525,7 @@ void GxsGroupFrameDialog::sharePublishKey()
shareUi.exec();
}
void GxsGroupFrameDialog::loadComment(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId, const QString &title)
void GxsGroupFrameDialog::loadComment(const RsGxsGroupId &grpId, const QVector<RsGxsMessageId>& msg_versions, const RsGxsMessageId &most_recent_msgId, const QString &title)
{
RsGxsCommentService *commentService = getCommentService();
if (!commentService) {
@ -533,7 +533,8 @@ void GxsGroupFrameDialog::loadComment(const RsGxsGroupId &grpId, const RsGxsMess
return;
}
GxsCommentDialog *commentDialog = commentWidget(msgId);
GxsCommentDialog *commentDialog = commentWidget(most_recent_msgId);
if (!commentDialog) {
QString comments = title;
if (title.length() > MAX_COMMENT_TITLE)
@ -544,12 +545,16 @@ void GxsGroupFrameDialog::loadComment(const RsGxsGroupId &grpId, const RsGxsMess
commentDialog = new GxsCommentDialog(this, mInterface->getTokenService(), commentService);
QWidget *commentHeader = createCommentHeaderWidget(grpId, msgId);
QWidget *commentHeader = createCommentHeaderWidget(grpId, most_recent_msgId);
if (commentHeader) {
commentDialog->setCommentHeader(commentHeader);
}
commentDialog->commentLoad(grpId, msgId);
std::set<RsGxsMessageId> msgv;
for(int i=0;i<msg_versions.size();++i)
msgv.insert(msg_versions[i]);
commentDialog->commentLoad(grpId, msgv,most_recent_msgId);
int index = ui->messageTabWidget->addTab(commentDialog, comments);
ui->messageTabWidget->setTabIcon(index, QIcon(IMAGE_COMMENT));
@ -620,12 +625,12 @@ GxsMessageFrameWidget *GxsGroupFrameDialog::createMessageWidget(const RsGxsGroup
connect(msgWidget, SIGNAL(groupChanged(QWidget*)), this, SLOT(messageTabInfoChanged(QWidget*)));
connect(msgWidget, SIGNAL(waitingChanged(QWidget*)), this, SLOT(messageTabWaitingChanged(QWidget*)));
connect(msgWidget, SIGNAL(loadComment(RsGxsGroupId,RsGxsMessageId,QString)), this, SLOT(loadComment(RsGxsGroupId,RsGxsMessageId,QString)));
connect(msgWidget, SIGNAL(loadComment(RsGxsGroupId,QVector<RsGxsMessageId>,RsGxsMessageId,QString)), this, SLOT(loadComment(RsGxsGroupId,QVector<RsGxsMessageId>,RsGxsMessageId,QString)));
return msgWidget;
}
GxsCommentDialog *GxsGroupFrameDialog::commentWidget(const RsGxsMessageId &msgId)
GxsCommentDialog *GxsGroupFrameDialog::commentWidget(const RsGxsMessageId& msgId)
{
int tabCount = ui->messageTabWidget->count();
for (int index = 0; index < tabCount; ++index) {

View File

@ -126,7 +126,7 @@ private slots:
void sharePublishKey();
void loadComment(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId, const QString &title);
void loadComment(const RsGxsGroupId &grpId, const QVector<RsGxsMessageId>& msg_versions,const RsGxsMessageId &most_recent_msgId, const QString &title);
private:
virtual QString text(TextType type) = 0;

View File

@ -54,7 +54,7 @@ public:
signals:
void groupChanged(QWidget *widget);
void waitingChanged(QWidget *widget);
void loadComment(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, const QString &title);
void loadComment(const RsGxsGroupId &groupId, const QVector<RsGxsMessageId>& msg_versions,const RsGxsMessageId &msgId, const QString &title);
protected:
virtual void setAllMessagesReadDo(bool read, uint32_t &token) = 0;

View File

@ -38,11 +38,15 @@
//#define ENABLE_GENERATE
#define CREATEMSG_CHANNELINFO 0x002
#define CREATEMSG_CHANNELINFO 0x002
#define CREATEMSG_CHANNEL_POST_INFO 0x003
// #define DEBUG_CREATE_GXS_MSG
/** Constructor */
CreateGxsChannelMsg::CreateGxsChannelMsg(const RsGxsGroupId &cId)
: QDialog (NULL, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint), mChannelId(cId) ,mCheckAttachment(true), mAutoMediaThumbNail(false)
CreateGxsChannelMsg::CreateGxsChannelMsg(const RsGxsGroupId &cId, RsGxsMessageId existing_post)
: QDialog (NULL, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint),
mChannelId(cId) , mOrigPostId(existing_post),mCheckAttachment(true), mAutoMediaThumbNail(false)
{
/* Invoke the Qt Designer generated object setup routine */
setupUi(this);
@ -50,7 +54,11 @@ CreateGxsChannelMsg::CreateGxsChannelMsg(const RsGxsGroupId &cId)
mChannelQueue = new TokenQueue(rsGxsChannels->getTokenService(), this);
headerFrame->setHeaderImage(QPixmap(":/images/channels.png"));
headerFrame->setHeaderText(tr("New Channel Post"));
if(!existing_post.isNull())
headerFrame->setHeaderText(tr("Edit Channel Post"));
else
headerFrame->setHeaderText(tr("New Channel Post"));
setAttribute ( Qt::WA_DeleteOnClose, true );
@ -337,43 +345,63 @@ void CreateGxsChannelMsg::parseRsFileListAttachments(const std::string &attachLi
}
void CreateGxsChannelMsg::addAttachment(const RsFileHash &hash, const std::string &fname, uint64_t size, bool local, const RsPeerId &srcId)
void CreateGxsChannelMsg::addAttachment(const RsFileHash &hash, const std::string &fname, uint64_t size, bool local, const RsPeerId &srcId, bool assume_file_ready)
{
/* add a SubFileItem to the attachment section */
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::addAttachment()";
std::cerr << std::endl;
#endif
/* add widget in for new destination */
uint32_t flags = SFI_TYPE_CHANNEL;
uint32_t flags = SFI_TYPE_CHANNEL | SFI_FLAG_ALLOW_DELETE ;
if(assume_file_ready)
flags |= SFI_FLAG_ASSUME_FILE_READY;
if (local)
{
flags |= SFI_STATE_LOCAL;
}
else
{
flags |= SFI_STATE_REMOTE;
}
SubFileItem *file = new SubFileItem(hash, fname, "", size, flags, srcId); // destroyed when fileFrame (this subfileitem) is destroyed
connect(file,SIGNAL(wantsToBeDeleted()),this,SLOT(deleteAttachment())) ;
mAttachments.push_back(file);
QLayout *layout = fileFrame->layout();
layout->addWidget(file);
if (mCheckAttachment)
{
checkAttachmentReady();
}
}
return;
void CreateGxsChannelMsg::deleteAttachment()
{
// grab the item who sent the request
SubFileItem *file_item = qobject_cast<SubFileItem *>(QObject::sender());
for(std::list<SubFileItem*>::iterator it(mAttachments.begin());it!=mAttachments.end();)
if(*it == file_item)
{
SubFileItem *item = *it ;
it = mAttachments.erase(it) ;
fileFrame->layout()->removeWidget(file_item) ;
delete item ;
}
else
++it;
}
void CreateGxsChannelMsg::addExtraFile()
{
/* add a SubFileItem to the attachment section */
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::addExtraFile() opening file dialog";
std::cerr << std::endl;
#endif
QStringList files;
if (misc::getOpenFileNames(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", files)) {
@ -386,8 +414,10 @@ void CreateGxsChannelMsg::addExtraFile()
void CreateGxsChannelMsg::addAttachment(const std::string &path)
{
/* add a SubFileItem to the attachment section */
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::addAttachment()";
std::cerr << std::endl;
#endif
if(mAutoMediaThumbNail)
setThumbNail(path, 2000);
@ -522,8 +552,10 @@ void CreateGxsChannelMsg::checkAttachmentReady()
void CreateGxsChannelMsg::cancelMsg()
{
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::cancelMsg() :"
<< "Deleting EXTRA attachments" << std::endl;
#endif
std::cerr << std::endl;
@ -555,6 +587,15 @@ void CreateGxsChannelMsg::newChannelMsg()
uint32_t token;
mChannelQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, groupIds, CREATEMSG_CHANNELINFO);
if(!mOrigPostId.isNull())
{
GxsMsgReq message_ids;
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
message_ids[mChannelId].push_back(mOrigPostId);
mChannelQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, message_ids, CREATEMSG_CHANNEL_POST_INFO);
}
}
}
@ -569,8 +610,10 @@ void CreateGxsChannelMsg::saveChannelInfo(const RsGroupMetaData &meta)
void CreateGxsChannelMsg::sendMsg()
{
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::sendMsg()";
std::cerr << std::endl;
#endif
/* construct message bits */
std::string subject = std::string(misc::removeNewLine(subjectEdit->text()).toUtf8());
@ -628,6 +671,7 @@ void CreateGxsChannelMsg::sendMessage(const std::string &subject, const std::str
post.mMeta.mThreadId.clear() ;
post.mMeta.mMsgId.clear() ;
post.mMeta.mOrigMsgId = mOrigPostId;
post.mMeta.mMsgName = subject;
post.mMsg = msg;
post.mFiles = files;
@ -686,10 +730,47 @@ void CreateGxsChannelMsg::addThumbnail()
thumbnail_label->setPixmap(picture);
}
void CreateGxsChannelMsg::loadChannelPostInfo(const uint32_t &token)
{
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::loadChannelPostInfo()";
std::cerr << std::endl;
#endif
std::vector<RsGxsChannelPost> posts;
rsGxsChannels->getPostData(token, posts);
if (posts.size() != 1)
{
std::cerr << "CreateGxsChannelMsg::loadChannelPostInfo() ERROR INVALID Number of posts in request" << std::endl;
return ;
}
// now populate the widget with the channel post data.
const RsGxsChannelPost& post = posts[0];
if(post.mMeta.mGroupId != mChannelId || post.mMeta.mMsgId != mOrigPostId)
{
std::cerr << "CreateGxsChannelMsg::loadChannelPostInfo() ERROR INVALID post ID or channel ID" << std::endl;
return ;
}
subjectEdit->setText(QString::fromUtf8(post.mMeta.mMsgName.c_str())) ;
msgEdit->setText(QString::fromUtf8(post.mMsg.c_str())) ;
for(std::list<RsGxsFile>::const_iterator it(post.mFiles.begin());it!=post.mFiles.end();++it)
addAttachment(it->mHash,it->mName,it->mSize,true,RsPeerId(),true);
picture.loadFromData(post.mThumbnail.mData,post.mThumbnail.mSize,"PNG");
thumbnail_label->setPixmap(picture);
}
void CreateGxsChannelMsg::loadChannelInfo(const uint32_t &token)
{
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::loadChannelInfo()";
std::cerr << std::endl;
#endif
std::list<RsGroupMetaData> groupInfo;
rsGxsChannels->getGroupSummary(token, groupInfo);
@ -708,8 +789,10 @@ void CreateGxsChannelMsg::loadChannelInfo(const uint32_t &token)
void CreateGxsChannelMsg::loadRequest(const TokenQueue *queue, const TokenRequest &req)
{
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::loadRequest() UserType: " << req.mUserType;
std::cerr << std::endl;
#endif
if (queue == mChannelQueue)
{
@ -719,6 +802,9 @@ void CreateGxsChannelMsg::loadRequest(const TokenQueue *queue, const TokenReques
case CREATEMSG_CHANNELINFO:
loadChannelInfo(req.mToken);
break;
case CREATEMSG_CHANNEL_POST_INFO:
loadChannelPostInfo(req.mToken);
break;
default:
std::cerr << "CreateGxsChannelMsg::loadRequest() UNKNOWN UserType ";
std::cerr << std::endl;

View File

@ -38,13 +38,13 @@ class CreateGxsChannelMsg : public QDialog, public TokenResponse, private Ui::Cr
public:
/** Default Constructor */
CreateGxsChannelMsg(const RsGxsGroupId& cId);
CreateGxsChannelMsg(const RsGxsGroupId& cId, RsGxsMessageId existing_post = RsGxsMessageId());
/** Default Destructor */
~CreateGxsChannelMsg();
void addAttachment(const std::string &path);
void addAttachment(const RsFileHash &hash, const std::string &fname, uint64_t size, bool local, const RsPeerId &srcId);
void addAttachment(const RsFileHash &hash, const std::string &fname, uint64_t size, bool local, const RsPeerId &srcId,bool assume_file_ready = false);
void newChannelMsg();
@ -60,6 +60,7 @@ protected:
private slots:
void addExtraFile();
void checkAttachmentReady();
void deleteAttachment();
void cancelMsg();
void sendMsg();
@ -71,6 +72,7 @@ private slots:
private:
void loadChannelInfo(const uint32_t &token);
void loadChannelPostInfo(const uint32_t &token);
void saveChannelInfo(const RsGroupMetaData &group);
void parseRsFileListAttachments(const std::string &attachList);
@ -78,7 +80,9 @@ private:
bool setThumbNail(const std::string& path, int frame);
RsGxsGroupId mChannelId;
RsGxsMessageId mOrigPostId;
RsGroupMetaData mChannelMeta;
RsMsgMetaData mOrigMeta;
bool mChannelMetaLoaded;
std::list<SubFileItem *> mAttachments;

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>581</width>
<height>479</height>
<width>875</width>
<height>659</height>
</rect>
</property>
<property name="acceptDrops">
@ -60,7 +60,7 @@
<bool>false</bool>
</property>
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<widget class="QWidget" name="channelPostTab">
<attribute name="title">
@ -302,8 +302,8 @@ p, li { white-space: pre-wrap; }
<rect>
<x>0</x>
<y>0</y>
<width>523</width>
<height>24</height>
<width>767</width>
<height>42</height>
</rect>
</property>
<property name="sizePolicy">

View File

@ -207,9 +207,9 @@ void GxsChannelPostsWidget::openChat(const RsPeerId & /*peerId*/)
}
// Callback from Widget->FeedHolder->ServiceDialog->CommentContainer->CommentDialog,
void GxsChannelPostsWidget::openComments(uint32_t /*type*/, const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, const QString &title)
void GxsChannelPostsWidget::openComments(uint32_t /*type*/, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId>& msg_versions,const RsGxsMessageId &msgId, const QString &title)
{
emit loadComment(groupId, msgId, title);
emit loadComment(groupId, msg_versions,msgId, title);
}
void GxsChannelPostsWidget::createMsg()
@ -398,7 +398,27 @@ void GxsChannelPostsWidget::filterChanged(int filter)
void GxsChannelPostsWidget::createPostItem(const RsGxsChannelPost &post, bool related)
{
GxsChannelPostItem *item = NULL;
if (related) {
if(!post.mMeta.mOrigMsgId.isNull())
{
FeedItem *feedItem = ui->feedWidget->findGxsFeedItem(post.mMeta.mGroupId, post.mMeta.mOrigMsgId);
item = dynamic_cast<GxsChannelPostItem*>(feedItem);
if(item)
{
ui->feedWidget->removeFeedItem(item) ;
RsGxsChannelGroup dummyGroup;
dummyGroup.mMeta.mGroupId = groupId();
dummyGroup.mMeta.mSubscribeFlags = 0xffffffff;
GxsChannelPostItem *item = new GxsChannelPostItem(this, 0, dummyGroup, post, true, false);
ui->feedWidget->addFeedItem(item, ROLE_PUBLISH, QDateTime::fromTime_t(post.mMeta.mPublishTs));
return ;
}
}
if (related)
{
FeedItem *feedItem = ui->feedWidget->findGxsFeedItem(post.mMeta.mGroupId, post.mMeta.mMsgId);
item = dynamic_cast<GxsChannelPostItem*>(feedItem);
}
@ -438,8 +458,6 @@ void GxsChannelPostsWidget::insertChannelPosts(std::vector<RsGxsChannelPost> &po
return;
}
std::vector<RsGxsChannelPost>::const_reverse_iterator it;
int count = posts.size();
int pos = 0;
@ -447,18 +465,127 @@ void GxsChannelPostsWidget::insertChannelPosts(std::vector<RsGxsChannelPost> &po
ui->feedWidget->setSortingEnabled(false);
}
for (it = posts.rbegin(); it != posts.rend(); ++it)
{
if (thread && thread->stopped()) {
break;
}
// collect new versions of posts if any
if (thread) {
thread->emitAddPost(qVariantFromValue(*it), related, ++pos, count);
} else {
createPostItem(*it, related);
#ifdef DEBUG_CHANNEL
std::cerr << "Inserting channel posts" << std::endl;
#endif
std::vector<uint32_t> new_versions ;
for (uint32_t i=0;i<posts.size();++i)
{
if(posts[i].mMeta.mOrigMsgId == posts[i].mMeta.mMsgId)
posts[i].mMeta.mOrigMsgId.clear();
#ifdef DEBUG_CHANNEL
std::cerr << " " << i << ": msg_id=" << posts[i].mMeta.mMsgId << ": orig msg id = " << posts[i].mMeta.mOrigMsgId << std::endl;
#endif
if(!posts[i].mMeta.mOrigMsgId.isNull())
new_versions.push_back(i) ;
}
#ifdef DEBUG_CHANNEL
std::cerr << "New versions: " << new_versions.size() << std::endl;
#endif
if(!new_versions.empty())
{
#ifdef DEBUG_CHANNEL
std::cerr << " New versions present. Replacing them..." << std::endl;
std::cerr << " Creating search map." << std::endl;
#endif
// make a quick search map
std::map<RsGxsMessageId,uint32_t> search_map ;
for (uint32_t i=0;i<posts.size();++i)
search_map[posts[i].mMeta.mMsgId] = i ;
for(uint32_t i=0;i<new_versions.size();++i)
{
#ifdef DEBUG_CHANNEL
std::cerr << " Taking care of new version at index " << new_versions[i] << std::endl;
#endif
uint32_t current_index = new_versions[i] ;
uint32_t source_index = new_versions[i] ;
RsGxsMessageId source_msg_id = posts[source_index].mMeta.mMsgId ;
// What we do is everytime we find a replacement post, we climb up the replacement graph until we find the original post
// (or the most recent version of it). When we reach this post, we replace it with the data of the source post.
// In the mean time, all other posts have their MsgId cleared, so that the posts are removed from the list.
std::vector<uint32_t> versions ;
std::map<RsGxsMessageId,uint32_t>::const_iterator vit ;
while(search_map.end() != (vit=search_map.find(posts[current_index].mMeta.mOrigMsgId)))
{
#ifdef DEBUG_CHANNEL
std::cerr << " post at index " << current_index << " replaces a post at position " << vit->second ;
#endif
// Now replace the post only if the new versionis more recent. It may happen indeed that the same post has been corrected multiple
// times. In this case, we only need to replace the post with the newest version
uint32_t prev_index = current_index ;
current_index = vit->second ;
if(posts[current_index].mMeta.mMsgId.isNull()) // This handles the branching situation where this post has been already erased. No need to go down further.
{
#ifdef DEBUG_CHANNEL
std::cerr << " already erased. Stopping." << std::endl;
#endif
break ;
}
if(posts[current_index].mMeta.mPublishTs < posts[source_index].mMeta.mPublishTs)
{
#ifdef DEBUG_CHANNEL
std::cerr << " and is more recent => following" << std::endl;
#endif
for(std::set<RsGxsMessageId>::const_iterator itt(posts[current_index].mOlderVersions.begin());itt!=posts[current_index].mOlderVersions.end();++itt)
posts[source_index].mOlderVersions.insert(*itt);
posts[source_index].mOlderVersions.insert(posts[current_index].mMeta.mMsgId);
posts[current_index].mMeta.mMsgId.clear(); // clear the msg Id so the post will be ignored
}
#ifdef DEBUG_CHANNEL
else
std::cerr << " but is older -> Stopping" << std::endl;
#endif
}
}
}
#ifdef DEBUG_CHANNEL
std::cerr << "Now adding posts..." << std::endl;
#endif
for (std::vector<RsGxsChannelPost>::const_reverse_iterator it = posts.rbegin(); it != posts.rend(); ++it)
{
#ifdef DEBUG_CHANNEL
std::cerr << " adding post: " << (*it).mMeta.mMsgId ;
#endif
if(!(*it).mMeta.mMsgId.isNull())
{
#ifdef DEBUG_CHANNEL
std::cerr << " added" << std::endl;
#endif
if (thread && thread->stopped())
break;
if (thread)
thread->emitAddPost(qVariantFromValue(*it), related, ++pos, count);
else
createPostItem(*it, related);
}
}
#ifdef DEBUG_CHANNEL
else
std::cerr << " skipped" << std::endl;
#endif
}
if (!thread) {
ui->feedWidget->setSortingEnabled(true);

View File

@ -61,7 +61,7 @@ public:
virtual QScrollArea *getScrollArea();
virtual void deleteFeedItem(QWidget *item, uint32_t type);
virtual void openChat(const RsPeerId& peerId);
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, const QString &title);
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &msg_versions, const RsGxsMessageId &msgId, const QString &title);
protected:
/* GxsMessageFramePostWidget */

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>793</width>
<height>465</height>
<width>880</width>
<height>557</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
@ -454,7 +454,7 @@
<string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt;&quot;&gt;Description&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textInteractionFlags">

View File

@ -1,5 +1,7 @@
<RCC>
<qresource prefix="/">
<file>icons/svg/hidden.svg</file>
<file>icons/svg/randomness.svg</file>
<file>icons/svg/password.svg</file>
<file>icons/stars/star0.png</file>
<file>icons/stars/star1.png</file>

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg4155"
version="1.1"
inkscape:version="0.91 r13725"
xml:space="preserve"
width="80"
height="80"
viewBox="0 0 80 80"
sodipodi:docname="hidden.svg"><metadata
id="metadata4161"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs4159"><linearGradient
id="linearGradient5584"
osb:paint="solid"><stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop5586" /></linearGradient></defs><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1366"
inkscape:window-height="706"
id="namedview4157"
showgrid="false"
inkscape:zoom="3.6195029"
inkscape:cx="37.953819"
inkscape:cy="49.057609"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="g4163" /><g
id="g4163"
inkscape:groupmode="layer"
inkscape:label="ink_ext_XXXXXX"
transform="matrix(1.25,0,0,-1.25,0,80)"><path
inkscape:connector-curvature="0"
id="path4167"
style="fill:#039bd5;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 64,32 C 64,14.327 49.673,0 32,0 14.327,0 0,14.327 0,32 0,49.673 14.327,64 32,64 49.673,64 64,49.673 64,32" /><g
transform="matrix(0.47818792,0,0,-0.47818794,8.3042308,56.181608)"
id="g3"><g
id="g5"><path
style="fill:#ffffff"
inkscape:connector-curvature="0"
d="M 69.322,44.716 49.715,64.323 C 60.438,64.072 69.071,55.438 69.322,44.716 Z"
id="path7" /><path
style="fill:#ffffff"
inkscape:connector-curvature="0"
d="M 97.204,45.789 C 96.755,45.26 90.959,38.559 81.802,32.235 l -6.2,6.2 c 5.99,3.954 10.559,8.275 13.011,10.806 -5.378,5.554 -20.913,19.728 -39.372,19.728 -1.334,0 -2.651,-0.082 -3.952,-0.222 l -7.439,7.438 c 3.639,0.91 7.449,1.451 11.391,1.451 26.426,0 47.098,-23.927 47.964,-24.946 1.701,-1.998 1.701,-4.9 -0.001,-6.901 z"
id="path9" /><path
style="fill:#ffffff"
inkscape:connector-curvature="0"
d="m 90.651,15.901 c 0,-0.266 -0.104,-0.52 -0.293,-0.707 l -7.071,-7.07 c -0.391,-0.391 -1.022,-0.391 -1.414,0 L 66.045,23.952 C 60.843,22.059 55.19,20.844 49.241,20.844 22.814,20.844 2.143,44.77 1.276,45.79 c -1.701,2 -1.701,4.902 10e-4,6.903 0.517,0.606 8.083,9.354 19.707,16.319 l -12.86,12.86 c -0.188,0.188 -0.293,0.441 -0.293,0.707 0,0.267 0.105,0.521 0.293,0.707 l 7.071,7.07 c 0.195,0.194 0.451,0.293 0.707,0.293 0.256,0 0.512,-0.099 0.707,-0.293 l 73.75,-73.75 c 0.187,-0.185 0.292,-0.439 0.292,-0.705 z M 9.869,49.241 C 13.5,45.49 21.767,37.812 32.436,33.22 c -2.081,3.166 -3.301,6.949 -3.301,11.021 0,4.665 1.601,8.945 4.27,12.352 l -6.124,6.123 C 19.129,58.196 12.89,52.361 9.869,49.241 Z"
id="path11" /></g></g></g></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -0,0 +1,197 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg4155"
version="1.1"
inkscape:version="0.91 r13725"
xml:space="preserve"
width="80"
height="80"
viewBox="0 0 80 80"
sodipodi:docname="randomness.svg"><metadata
id="metadata4161"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs4159" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1366"
inkscape:window-height="706"
id="namedview4157"
showgrid="false"
inkscape:zoom="5.11875"
inkscape:cx="54.735476"
inkscape:cy="40.772004"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="g4163" /><g
id="g4163"
inkscape:groupmode="layer"
inkscape:label="ink_ext_XXXXXX"
transform="matrix(1.25,0,0,-1.25,0,80)"><path
inkscape:connector-curvature="0"
id="path4167"
style="fill:#039bd5;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 64,32 C 64,14.327 49.673,0 32,0 14.327,0 0,14.327 0,32 0,49.673 14.327,64 32,64 49.673,64 64,49.673 64,32" /><g
transform="matrix(1.4341283,-0.03685349,-0.03685349,-1.4341283,6.7291558,58.393566)"
id="g3"><g
id="g5"><polygon
style="fill:#ffffff"
points="11.78,8.598 7.526,6.141 7.526,11.054 "
id="polygon7" /><polygon
style="fill:#ffffff"
points="11.78,14.738 7.526,12.282 7.526,17.193 "
id="polygon9" /><polygon
style="fill:#ffffff"
points="11.78,27.02 7.526,24.562 7.526,29.475 "
id="polygon11" /><polygon
style="fill:#ffffff"
points="12.135,27.635 7.881,30.09 12.135,32.546 "
id="polygon13" /><polygon
style="fill:#ffffff"
points="12.135,15.352 7.881,17.809 12.135,20.266 "
id="polygon15" /><polygon
style="fill:#ffffff"
points="12.135,9.211 7.881,11.668 12.135,14.124 "
id="polygon17" /><polygon
style="fill:#ffffff"
points="12.135,3.071 7.881,5.527 12.135,7.983 "
id="polygon19" /><polygon
style="fill:#ffffff"
points="17.099,5.527 12.844,3.071 12.844,7.983 "
id="polygon21" /><polygon
style="fill:#ffffff"
points="17.099,11.668 12.844,9.211 12.844,14.124 "
id="polygon23" /><polygon
style="fill:#ffffff"
points="17.099,17.809 12.844,15.352 12.844,20.266 "
id="polygon25" /><polygon
style="fill:#ffffff"
points="17.099,23.949 12.844,21.493 12.844,26.405 "
id="polygon27" /><polygon
style="fill:#ffffff"
points="17.099,30.09 12.844,27.635 12.844,32.546 "
id="polygon29" /><polygon
style="fill:#ffffff"
points="17.453,30.704 13.199,33.16 17.453,35.616 "
id="polygon31" /><polygon
style="fill:#ffffff"
points="17.453,24.562 13.199,27.02 17.453,29.475 "
id="polygon33" /><polygon
style="fill:#ffffff"
points="17.453,18.422 13.199,20.879 17.453,23.335 "
id="polygon35" /><polygon
style="fill:#ffffff"
points="17.453,12.282 13.199,14.738 17.453,17.193 "
id="polygon37" /><polygon
style="fill:#ffffff"
points="17.453,0 13.199,2.456 17.453,4.913 "
id="polygon39" /><polygon
style="fill:#ffffff"
points="6.462,11.668 2.208,9.211 2.208,14.124 "
id="polygon41" /><polygon
style="fill:#ffffff"
points="6.462,17.809 2.208,15.352 2.208,20.266 "
id="polygon43" /><polygon
style="fill:#ffffff"
points="6.462,23.949 2.208,21.493 2.208,26.405 "
id="polygon45" /><polygon
style="fill:#ffffff"
points="6.817,24.562 2.562,27.02 6.817,29.475 "
id="polygon47" /><polygon
style="fill:#ffffff"
points="6.817,18.422 2.562,20.879 6.817,23.335 "
id="polygon49" /><polygon
style="fill:#ffffff"
points="6.817,12.282 2.562,14.738 6.817,17.193 "
id="polygon51" /><polygon
style="fill:#ffffff"
points="6.817,6.141 2.562,8.598 6.817,11.054 "
id="polygon53" /><polygon
style="fill:#ffffff"
points="22.416,2.456 18.162,0 18.162,4.913 "
id="polygon55" /><polygon
style="fill:#ffffff"
points="22.416,14.738 18.162,12.282 18.162,17.193 "
id="polygon57" /><polygon
style="fill:#ffffff"
points="22.416,20.879 18.162,18.422 18.162,23.335 "
id="polygon59" /><polygon
style="fill:#ffffff"
points="22.416,27.02 18.162,24.562 18.162,29.475 "
id="polygon61" /><polygon
style="fill:#ffffff"
points="22.416,33.16 18.162,30.704 18.162,35.616 "
id="polygon63" /><polygon
style="fill:#ffffff"
points="22.771,27.635 18.517,30.09 22.771,32.546 "
id="polygon65" /><polygon
style="fill:#ffffff"
points="22.771,21.493 18.517,23.949 22.771,26.405 "
id="polygon67" /><polygon
style="fill:#ffffff"
points="22.771,15.352 18.517,17.809 22.771,20.266 "
id="polygon69" /><polygon
style="fill:#ffffff"
points="22.771,9.211 18.517,11.668 22.771,14.124 "
id="polygon71" /><polygon
style="fill:#ffffff"
points="22.771,3.071 18.517,5.527 22.771,7.983 "
id="polygon73" /><polygon
style="fill:#ffffff"
points="27.735,5.527 23.479,3.071 23.479,7.983 "
id="polygon75" /><polygon
style="fill:#ffffff"
points="27.735,11.668 23.479,9.211 23.479,14.124 "
id="polygon77" /><polygon
style="fill:#ffffff"
points="27.735,17.809 23.479,15.352 23.479,20.266 "
id="polygon79" /><polygon
style="fill:#ffffff"
points="27.735,30.09 23.479,27.635 23.479,32.546 "
id="polygon81" /><polygon
style="fill:#ffffff"
points="28.089,24.562 23.835,27.02 28.089,29.475 "
id="polygon83" /><polygon
style="fill:#ffffff"
points="28.089,12.282 23.835,14.738 28.089,17.193 "
id="polygon85" /><polygon
style="fill:#ffffff"
points="28.089,6.141 23.835,8.598 28.089,11.054 "
id="polygon87" /><polygon
style="fill:#ffffff"
points="33.052,8.598 28.798,6.141 28.798,11.054 "
id="polygon89" /><polygon
style="fill:#ffffff"
points="33.052,14.738 28.798,12.282 28.798,17.193 "
id="polygon91" /><polygon
style="fill:#ffffff"
points="33.052,20.879 28.798,18.422 28.798,23.335 "
id="polygon93" /><polygon
style="fill:#ffffff"
points="33.052,27.02 28.798,24.562 28.798,29.475 "
id="polygon95" /><polygon
style="fill:#ffffff"
points="33.408,21.493 29.153,23.949 33.408,26.405 "
id="polygon97" /><polygon
style="fill:#ffffff"
points="33.408,15.352 29.153,17.809 33.408,20.266 "
id="polygon99" /><polygon
style="fill:#ffffff"
points="33.408,9.211 29.153,11.668 33.408,14.124 "
id="polygon101" /></g></g></g></svg>

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -1,5 +1,6 @@
<RCC>
<qresource prefix="/">
<file>images/logo/background.png</file>
<file>images/logo/logo_spash2.png</file>
<file>images/network_map.png</file>
<file>images/global_switch_on.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

View File

@ -665,49 +665,49 @@ IdEditDialog QLabel#info_label
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2);
}
GenCertDialog QComboBox#genPGPuser {
border: 4px solid #0099cc;
border: 2px solid #0099cc;
border-radius: 6px;
background: white;
font: bold;
}
GenCertDialog QSpinBox#hiddenport_spinBox {
border: 4px solid #0099cc;
border: 2px solid #0099cc;
border-radius: 6px;
background: white;
font: bold;
}
GenCertDialog QLineEdit#hiddenaddr_input {
border: 4px solid #0099cc;
border: 2px solid #0099cc;
border-radius: 6px;
background: white;
font: bold;
}
GenCertDialog QLineEdit#password_input_2 {
border: 4px solid #0099cc;
border: 2px solid #0099cc;
border-radius: 6px;
background: white;
font: bold;
}
GenCertDialog QLineEdit#password_input {
border: 4px solid #0099cc;
border: 2px solid #0099cc;
border-radius: 6px;
background: white;
font: bold;
}
GenCertDialog QLineEdit#nickname_input {
border: 4px solid #0099cc;
border: 2px solid #0099cc;
border-radius: 6px;
background: white;
font: bold;
}
GenCertDialog QLineEdit#node_input {
border: 4px solid #0099cc;
border: 2px solid #0099cc;
border-radius: 6px;
background: white;
font: bold;
}
GenCertDialog QLineEdit#name_input {
border: 4px solid #0099cc;
border: 2px solid #0099cc;
border-radius: 6px;
background: white;
font: bold;
@ -772,4 +772,14 @@ StartDialog QPushButton#loadButton {
StartDialog QPushButton#loadButton:hover {
border-image: url(:/images/btn_blue_hover.png) 4;
}
}
StartDialog QFrame#loginframe{
background-image: url(:/images/logo/background.png);
background-repeat: repeat;
}
GenCertDialog QFrame#profileframe{
background-image: url(:/images/logo/background.png);
background-repeat: repeat;
}

View File

@ -416,7 +416,7 @@ ChatPage::load()
void ChatPage::on_pushButtonChangeChatFont_clicked()
{
bool ok;
QFont font = QFontDialog::getFont(&ok, fontTempChat, this);
QFont font = QFontDialog::getFont(&ok, fontTempChat, this, tr("Choose your default font for Chat."),QFontDialog::DontUseNativeDialog);
if (ok) {
fontTempChat = font;
// using fontTempChat.rawname() does not always work!
@ -424,6 +424,7 @@ void ChatPage::on_pushButtonChangeChatFont_clicked()
QStringList fontname = fontTempChat.toString().split(",");
ui.labelChatFontPreview->setText(fontname[0]);
ui.labelChatFontPreview->setFont(fontTempChat);
updateChatParams();
}
}

View File

@ -14,7 +14,7 @@
<item row="3" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>2</number>
<number>0</number>
</property>
<widget class="QWidget" name="general">
<attribute name="title">
@ -866,7 +866,7 @@
<enum>QTabWidget::North</enum>
</property>
<property name="currentIndex">
<number>2</number>
<number>0</number>
</property>
<widget class="QWidget" name="publicTab">
<attribute name="title">

View File

@ -0,0 +1,448 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 20011, RetroShare Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#include <iostream>
#include <QTimer>
#include <QObject>
#include <QFontMetrics>
#include <QWheelEvent>
#include <time.h>
#include <QMenu>
#include <QPainter>
#include <QStylePainter>
#include <QLayout>
#include <QHeaderView>
#include <retroshare/rsgxstrans.h>
#include <retroshare/rspeers.h>
#include <retroshare/rsidentity.h>
#include <retroshare/rsgxstrans.h>
#include "GxsTransportStatistics.h"
#include "gui/Identity/IdDetailsDialog.h"
#include "gui/settings/rsharesettings.h"
#include "util/QtVersion.h"
#include "gui/common/UIStateHelper.h"
#include "util/misc.h"
#define COL_ID 0
#define COL_DESTINATION 1
#define COL_NICKNAME 2
#define COL_DATASTATUS 3
#define COL_DATASIZE 4
#define COL_DATAHASH 5
#define COL_SEND 6
#define COL_GROUP_ID 7
static const int PARTIAL_VIEW_SIZE = 9 ;
static const int MAX_TUNNEL_REQUESTS_DISPLAY = 10 ;
static const int GXSTRANS_STATISTICS_DELAY_BETWEEN_GROUP_REQ = 30 ; // never request more than every 30 secs.
#define GXSTRANS_GROUP_META 0x01
#define GXSTRANS_GROUP_DATA 0x02
// static QColor colorScale(float f)
// {
// if(f == 0)
// return QColor::fromHsv(0,0,192) ;
// else
// return QColor::fromHsv((int)((1.0-f)*280),200,255) ;
// }
GxsTransportStatistics::GxsTransportStatistics(QWidget *parent)
: RsAutoUpdatePage(2000,parent)
{
setupUi(this) ;
mStateHelper = new UIStateHelper(this);
mStateHelper->addWidget(GXSTRANS_GROUP_META, treeWidget);
mTransQueue = new TokenQueue(rsGxsTrans->getTokenService(), this);
m_bProcessSettings = false;
mLastGroupReqTS = 0 ;
//_router_F->setWidget( _tst_CW = new GxsTransportStatisticsWidget() ) ;
/* Set header resize modes and initial section sizes Uploads TreeView*/
QHeaderView_setSectionResizeMode(treeWidget->header(), QHeaderView::ResizeToContents);
connect(treeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(CustomPopupMenu(QPoint)));
// load settings
processSettings(true);
}
GxsTransportStatistics::~GxsTransportStatistics()
{
// save settings
processSettings(false);
}
void GxsTransportStatistics::processSettings(bool bLoad)
{
m_bProcessSettings = true;
Settings->beginGroup(QString("GxsTransportStatistics"));
if (bLoad) {
// load settings
// state of splitter
//splitter->restoreState(Settings->value("Splitter").toByteArray());
} else {
// save settings
// state of splitter
//Settings->setValue("Splitter", splitter->saveState());
}
Settings->endGroup();
m_bProcessSettings = false;
}
void GxsTransportStatistics::CustomPopupMenu( QPoint )
{
QMenu contextMnu( this );
QTreeWidgetItem *item = treeWidget->currentItem();
if (item) {
contextMnu.addAction(QIcon(":/images/info16.png"), tr("Details"), this, SLOT(personDetails()));
}
contextMnu.exec(QCursor::pos());
}
void GxsTransportStatistics::updateDisplay()
{
time_t now = time(NULL) ;
if(mLastGroupReqTS + GXSTRANS_STATISTICS_DELAY_BETWEEN_GROUP_REQ < now)
{
requestGroupMeta();
mLastGroupReqTS = now ;
}
//_tst_CW->updateContent() ;
updateContent();
}
QString GxsTransportStatistics::getPeerName(const RsPeerId &peer_id)
{
static std::map<RsPeerId, QString> names ;
std::map<RsPeerId,QString>::const_iterator it = names.find(peer_id) ;
if( it != names.end())
return it->second ;
else
{
RsPeerDetails detail ;
if(!rsPeers->getPeerDetails(peer_id,detail))
return tr("Unknown Peer");
return (names[peer_id] = QString::fromUtf8(detail.name.c_str())) ;
}
}
static QString getStatusString(GxsTransSendStatus status)
{
switch(status)
{
case GxsTransSendStatus::PENDING_PROCESSING : return QObject::tr("Processing") ;
case GxsTransSendStatus::PENDING_PREFERRED_GROUP : return QObject::tr("Choosing group") ;
case GxsTransSendStatus::PENDING_RECEIPT_CREATE : return QObject::tr("Creating receipt") ;
case GxsTransSendStatus::PENDING_RECEIPT_SIGNATURE : return QObject::tr("Signing receipt") ;
case GxsTransSendStatus::PENDING_SERIALIZATION : return QObject::tr("Serializing") ;
case GxsTransSendStatus::PENDING_PAYLOAD_CREATE : return QObject::tr("Creating payload") ;
case GxsTransSendStatus::PENDING_PAYLOAD_ENCRYPT : return QObject::tr("Encrypting payload") ;
case GxsTransSendStatus::PENDING_PUBLISH : return QObject::tr("Publishing") ;
case GxsTransSendStatus::PENDING_RECEIPT_RECEIVE : return QObject::tr("Waiting for receipt") ;
case GxsTransSendStatus::RECEIPT_RECEIVED : return QObject::tr("Receipt received") ;
case GxsTransSendStatus::FAILED_RECEIPT_SIGNATURE : return QObject::tr("Receipt signature failed") ;
case GxsTransSendStatus::FAILED_ENCRYPTION : return QObject::tr("Encryption failed") ;
case GxsTransSendStatus::UNKNOWN :
default : return QObject::tr("Unknown") ;
}
}
void GxsTransportStatistics::updateContent()
{
RsGxsTrans::GxsTransStatistics transinfo ;
rsGxsTrans->getStatistics(transinfo) ;
treeWidget->clear();
time_t now = time(NULL) ;
groupBox->setTitle(tr("Pending packets")+": " + QString::number(transinfo.outgoing_records.size()) );
for(uint32_t i=0;i<transinfo.outgoing_records.size();++i)
{
const RsGxsTransOutgoingRecord& rec(transinfo.outgoing_records[i]) ;
QTreeWidgetItem *item = new QTreeWidgetItem();
treeWidget->addTopLevelItem(item);
RsIdentityDetails details ;
rsIdentity->getIdDetails(rec.recipient,details);
QString nickname = QString::fromUtf8(details.mNickname.c_str());
if(nickname.isEmpty())
nickname = tr("Unknown");
item -> setData(COL_ID, Qt::DisplayRole, QString::number(rec.trans_id,16).rightJustified(8,'0'));
item -> setData(COL_NICKNAME, Qt::DisplayRole, nickname ) ;
item -> setData(COL_DESTINATION, Qt::DisplayRole, QString::fromStdString(rec.recipient.toStdString()));
item -> setData(COL_DATASTATUS, Qt::DisplayRole, getStatusString(rec.status));
item -> setData(COL_DATASIZE, Qt::DisplayRole, misc::friendlyUnit(rec.data_size));
item -> setData(COL_DATAHASH, Qt::DisplayRole, QString::fromStdString(rec.data_hash.toStdString()));
item -> setData(COL_SEND, Qt::DisplayRole, QString::number(now - rec.send_TS));
item -> setData(COL_GROUP_ID, Qt::DisplayRole, QString::fromStdString(rec.group_id.toStdString()));
}
}
void GxsTransportStatistics::personDetails()
{
QTreeWidgetItem *item = treeWidget->currentItem();
std::string id = item->text(COL_DESTINATION).toStdString();
if (id.empty()) {
return;
}
IdDetailsDialog *dialog = new IdDetailsDialog(RsGxsGroupId(id));
dialog->show();
}
GxsTransportStatisticsWidget::GxsTransportStatisticsWidget(QWidget *parent)
: QWidget(parent)
{
float size = QFontMetricsF(font()).height() ;
float fact = size/14.0 ;
maxWidth = 400*fact ;
maxHeight = 0 ;
mCurrentN = PARTIAL_VIEW_SIZE/2+1 ;
}
void GxsTransportStatisticsWidget::updateContent()
{
RsGxsTrans::GxsTransStatistics transinfo ;
rsGxsTrans->getStatistics(transinfo) ;
float size = QFontMetricsF(font()).height() ;
float fact = size/14.0 ;
// What do we need to draw?
//
// Statistics about GxsTransport
// - prefered group ID
//
// Own key ids
// key service id description
//
// Data items
// Msg id Local origin Destination Time Status
//
QPixmap tmppixmap(maxWidth, maxHeight);
tmppixmap.fill(Qt::transparent);
setFixedHeight(maxHeight);
QPainter painter(&tmppixmap);
painter.initFrom(this);
painter.setPen(QColor::fromRgb(0,0,0)) ;
QFont times_f(font());//"Times") ;
QFont monospace_f("Monospace") ;
monospace_f.setStyleHint(QFont::TypeWriter) ;
monospace_f.setPointSize(font().pointSize()) ;
QFontMetricsF fm_monospace(monospace_f) ;
QFontMetricsF fm_times(times_f) ;
static const int cellx = fm_monospace.width(QString(" ")) ;
static const int celly = fm_monospace.height() ;
maxHeight = 500*fact ;
// std::cerr << "Drawing into pixmap of size " << maxWidth << "x" << maxHeight << std::endl;
// draw...
int ox=5*fact,oy=5*fact ;
painter.setFont(times_f) ;
painter.drawText(ox,oy+celly,tr("Preferred group Id")+":" + QString::fromStdString(transinfo.prefered_group_id.toStdString())) ; oy += celly*2 ;
oy += celly ;
oy += celly ;
// update the pixmap
//
pixmap = tmppixmap;
maxHeight = oy ;
}
void GxsTransportStatisticsWidget::wheelEvent(QWheelEvent *e)
{
}
QString GxsTransportStatisticsWidget::speedString(float f)
{
if(f < 1.0f)
return QString("0 B/s") ;
if(f < 1024.0f)
return QString::number((int)f)+" B/s" ;
return QString::number(f/1024.0,'f',2) + " KB/s";
}
void GxsTransportStatisticsWidget::paintEvent(QPaintEvent */*event*/)
{
QStylePainter(this).drawPixmap(0, 0, pixmap);
}
void GxsTransportStatisticsWidget::resizeEvent(QResizeEvent *event)
{
QRect TaskGraphRect = geometry();
maxWidth = TaskGraphRect.width();
maxHeight = TaskGraphRect.height() ;
QWidget::resizeEvent(event);
updateContent();
}
void GxsTransportStatistics::loadRequest(const TokenQueue *queue, const TokenRequest &req)
{
std::cerr << "GxsTransportStatistics::loadRequest() UserType: " << req.mUserType;
std::cerr << std::endl;
if (queue != mTransQueue)
{
/* now switch on req */
switch(req.mUserType)
{
case GXSTRANS_GROUP_META: loadGroupMeta(req.mToken);
break;
case GXSTRANS_GROUP_DATA: loadGroupData(req.mToken);
break;
default:
std::cerr << "GxsTransportStatistics::loadRequest() ERROR: INVALID TYPE";
std::cerr << std::endl;
break;
}
}
}
void GxsTransportStatistics::requestGroupMeta()
{
mStateHelper->setLoading(GXSTRANS_GROUP_META, true);
std::cerr << "GxsTransportStatisticsWidget::requestGroupMeta()";
std::cerr << std::endl;
mTransQueue->cancelActiveRequestTokens(GXSTRANS_GROUP_META);
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_GROUP_META;
uint32_t token;
mTransQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, GXSTRANS_GROUP_META);
}
void GxsTransportStatistics::loadGroupMeta(const uint32_t& token)
{
mStateHelper->setLoading(GXSTRANS_GROUP_META, false);
std::cerr << "GxsTransportStatisticsWidget::loadGroupMeta()";
std::cerr << std::endl;
// ui.treeWidget_membership->clear();
std::list<RsGroupMetaData> groupInfo;
std::list<RsGroupMetaData>::iterator vit;
if (!rsGxsTrans->getGroupSummary(token,groupInfo))
{
std::cerr << "GxsTransportStatistics::loadGroupMeta() Error getting GroupMeta";
std::cerr << std::endl;
mStateHelper->setActive(GXSTRANS_GROUP_META, false);
return;
}
mStateHelper->setActive(GXSTRANS_GROUP_META, true);
// /* add the top level item */
// QTreeWidgetItem *personalCirclesItem = new QTreeWidgetItem();
// personalCirclesItem->setText(0, tr("Personal Circles"));
// ui.treeWidget_membership->addTopLevelItem(personalCirclesItem);
//
// QTreeWidgetItem *externalAdminCirclesItem = new QTreeWidgetItem();
// externalAdminCirclesItem->setText(0, tr("External Circles (Admin)"));
// ui.treeWidget_membership->addTopLevelItem(externalAdminCirclesItem);
//
// QTreeWidgetItem *externalSubCirclesItem = new QTreeWidgetItem();
// externalSubCirclesItem->setText(0, tr("External Circles (Subscribed)"));
// ui.treeWidget_membership->addTopLevelItem(externalSubCirclesItem);
//
// QTreeWidgetItem *externalOtherCirclesItem = new QTreeWidgetItem();
// externalOtherCirclesItem->setText(0, tr("External Circles (Other)"));
// ui.treeWidget_membership->addTopLevelItem(externalOtherCirclesItem);
for(vit = groupInfo.begin(); vit != groupInfo.end(); ++vit)
{
/* Add Widget, and request Pages */
std::cerr << "GxsTransportStatisticsWidget::loadGroupMeta() GroupId: " << vit->mGroupId << " Group: " << vit->mGroupName << std::endl;
// QTreeWidgetItem *groupItem = new QTreeWidgetItem();
// groupItem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QString::fromUtf8(vit->mGroupName.c_str()));
// groupItem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPID, QString::fromStdString(vit->mGroupId.toStdString()));
// if (vit->mCircleType == GXS_CIRCLE_TYPE_LOCAL)
// personalCirclesItem->addChild(groupItem);
// else
// {
// if (vit->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)
// externalAdminCirclesItem->addChild(groupItem);
// else if (vit->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED)
// externalSubCirclesItem->addChild(groupItem);
// else
// externalOtherCirclesItem->addChild(groupItem);
// }
}
}
void GxsTransportStatistics::loadGroupData(const uint32_t& token)
{
std::cerr << __PRETTY_FUNCTION__ << ": not implemented." << std::endl;
}

View File

@ -0,0 +1,97 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 20011, RetroShare Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#pragma once
#include <QPoint>
#include <retroshare/rsgrouter.h>
#include <retroshare/rstypes.h>
#include "util/TokenQueue.h"
#include "RsAutoUpdatePage.h"
#include "ui_GxsTransportStatistics.h"
class GxsTransportStatisticsWidget ;
class UIStateHelper;
class GxsTransportStatistics: public RsAutoUpdatePage, public TokenResponse, public Ui::GxsTransportStatistics
{
Q_OBJECT
public:
GxsTransportStatistics(QWidget *parent = NULL) ;
~GxsTransportStatistics();
// Cache for peer names.
static QString getPeerName(const RsPeerId& peer_id) ;
virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req) ;
void updateContent() ;
private slots:
/** Create the context popup menu and it's submenus */
void CustomPopupMenu( QPoint point );
void personDetails();
private:
void loadGroupData(const uint32_t& token);
void loadGroupMeta(const uint32_t& token);
void requestGroupData();
void requestGroupMeta();
void processSettings(bool bLoad);
bool m_bProcessSettings;
virtual void updateDisplay() ;
GxsTransportStatisticsWidget *_tst_CW ;
TokenQueue *mTransQueue ;
UIStateHelper *mStateHelper;
uint32_t mLastGroupReqTS ;
} ;
class GxsTransportStatisticsWidget: public QWidget
{
Q_OBJECT
public:
GxsTransportStatisticsWidget(QWidget *parent = NULL) ;
virtual void paintEvent(QPaintEvent *event) ;
virtual void resizeEvent(QResizeEvent *event);
virtual void wheelEvent(QWheelEvent *event);
void updateContent() ;
private:
static QString speedString(float f) ;
QPixmap pixmap ;
int maxWidth,maxHeight ;
int mCurrentN ;
int mNumberOfKnownKeys ;
int mMinWheelZoneX ;
int mMinWheelZoneY ;
int mMaxWheelZoneX ;
int mMaxWheelZoneY ;
};

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GxsTransportStatistics</class>
<widget class="QWidget" name="GxsTransportStatistics">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1468</width>
<height>659</height>
</rect>
</property>
<property name="windowTitle">
<string>Router Statistics</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QScrollArea" name="_router_F">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1432</width>
<height>305</height>
</rect>
</property>
</widget>
</widget>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>GroupBox</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QTreeWidget" name="treeWidget">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<column>
<property name="text">
<string>ID</string>
</property>
</column>
<column>
<property name="text">
<string>Destination ID</string>
</property>
</column>
<column>
<property name="text">
<string>Destination Name</string>
</property>
</column>
<column>
<property name="text">
<string>Data status</string>
</property>
</column>
<column>
<property name="text">
<string>Data size</string>
</property>
</column>
<column>
<property name="text">
<string>Data hash</string>
</property>
</column>
<column>
<property name="text">
<string>Sending time (secs ago)</string>
</property>
</column>
<column>
<property name="text">
<string>Group ID</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -36,6 +36,7 @@
#include <gui/statistics/TurtleRouterStatistics.h>
#include <gui/statistics/GlobalRouterStatistics.h>
#include <gui/statistics/GxsTransportStatistics.h>
#include <gui/statistics/BwCtrlWindow.h>
#include <gui/statistics/DhtWindow.h>
@ -50,10 +51,10 @@
#define IMAGE_DHT ":/images/dht32.png"
#define IMAGE_TURTLE ":images/turtle.png"
#define IMAGE_BWGRAPH ":/images/ksysguard.png"
#define IMAGE_GLOBALROUTER ":/images/network32.png"
#define IMAGE_BANDWIDTH ":images/office-chart-area-stacked.png"
#define IMAGE_RTT ":images/office-chart-line.png"
#define IMAGE_BWGRAPH ":/images/ksysguard.png"
#define IMAGE_GLOBALROUTER ":/images/network32.png"
#define IMAGE_BANDWIDTH ":images/office-chart-area-stacked.png"
#define IMAGE_RTT ":images/office-chart-line.png"
/********************************************** STATIC WINDOW *************************************/
StatisticsWindow * StatisticsWindow::mInstance = NULL;
@ -133,6 +134,9 @@ void StatisticsWindow::initStackedPage()
ui->stackPages->add(grsdlg = new GlobalRouterStatistics(ui->stackPages),
action = createPageAction(QIcon(IMAGE_GLOBALROUTER), tr("Global Router"), grp));
ui->stackPages->add(gxsdlg = new GxsTransportStatistics(ui->stackPages),
action = createPageAction(QIcon(IMAGE_GLOBALROUTER), tr("Gxs Transport"), grp));
ui->stackPages->add(rttdlg = new RttStatistics(ui->stackPages),
action = createPageAction(QIcon(IMAGE_RTT), tr("RTT Statistics"), grp));

View File

@ -37,6 +37,7 @@ class DhtWindow;
class BwCtrlWindow;
class TurtleRouterStatistics;
class GlobalRouterStatistics;
class GxsTransportStatistics;
class RttStatistics;
class StatisticsWindow : public QMainWindow {
@ -53,6 +54,7 @@ public:
DhtWindow *dhtw;
GlobalRouterStatistics *grsdlg;
GxsTransportStatistics *gxsdlg;
BwCtrlWindow *bwdlg;
TurtleRouterStatistics *trsdlg;
RttStatistics *rttdlg;

View File

@ -374,6 +374,7 @@ HEADERS += rshare.h \
gui/statistics/BandwidthStatsWidget.h \
gui/statistics/DhtWindow.h \
gui/statistics/GlobalRouterStatistics.h \
gui/statistics/GxsTransportStatistics.h \
gui/statistics/StatisticsWindow.h \
gui/statistics/BwCtrlWindow.h \
gui/statistics/RttStatistics.h \
@ -680,6 +681,7 @@ FORMS += gui/StartDialog.ui \
gui/statistics/TurtleRouterDialog.ui \
gui/statistics/TurtleRouterStatistics.ui \
gui/statistics/GlobalRouterStatistics.ui \
gui/statistics/GxsTransportStatistics.ui \
gui/statistics/StatisticsWindow.ui \
gui/statistics/BwCtrlWindow.ui \
gui/statistics/RttStatistics.ui \
@ -917,6 +919,7 @@ SOURCES += main.cpp \
gui/statistics/TurtleRouterDialog.cpp \
gui/statistics/TurtleRouterStatistics.cpp \
gui/statistics/GlobalRouterStatistics.cpp \
gui/statistics/GxsTransportStatistics.cpp \
gui/statistics/StatisticsWindow.cpp \
gui/statistics/BwCtrlWindow.cpp \
gui/statistics/RttStatistics.cpp \