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) sqlcipher: libs/sqlcipher-$(SQLCIPHER_VERSION)
$(DOWNLOAD_PATH)/tcl$(TCL_VERSION)-src.tar.gz: $(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: $(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 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) ; RsTemporaryMemory mem(total_size) ;
uint32_t offset = 0 ; uint32_t offset = 0 ;
signature_serializer.serialise(data_item,mem,&total_size) ; uint32_t tmp_size = total_size ;
offset += signed_data_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) ; 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) ; return RsDirUtil::sha1sum(mem,total_size) ;
} }

View file

@ -1576,11 +1576,20 @@ bool RsGxsDataAccess::getGroupStatistic(GroupStatisticRequest *req)
req->mGroupStatistic.mNumChildMsgsNew = 0; req->mGroupStatistic.mNumChildMsgsNew = 0;
req->mGroupStatistic.mNumChildMsgsUnread = 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) for(uint32_t i = 0; i < msgMetaV.size(); ++i)
{ {
RsGxsMsgMetaData* m = msgMetaV[i]; RsGxsMsgMetaData* m = msgMetaV[i];
req->mGroupStatistic.mTotalSizeOfMsgs += m->mMsgSize + m->serial_size(); 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 (IS_MSG_NEW(m->mMsgStatus))
{ {
if (m->mParentId.isNull()) if (m->mParentId.isNull())

View file

@ -16,11 +16,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "util/rsdir.h"
#include "gxstrans/p3gxstrans.h" #include "gxstrans/p3gxstrans.h"
#include "util/stacktrace.h" #include "util/stacktrace.h"
typedef unsigned int uint; typedef unsigned int uint;
RsGxsTrans *rsGxsTrans = NULL ;
p3GxsTrans::~p3GxsTrans() p3GxsTrans::~p3GxsTrans()
{ {
p3Config::saveConfiguration(); 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, bool p3GxsTrans::sendMail( RsGxsTransId& mailId,
GxsTransSubServices service, GxsTransSubServices service,
const RsGxsId& own_gxsid, const RsGxsId& recipient, const RsGxsId& own_gxsid, const RsGxsId& recipient,
@ -120,9 +152,9 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
&& meta.mGroupId != mPreferredGroupId; && meta.mGroupId != mPreferredGroupId;
if(shoudlSubscribe) if(shoudlSubscribe)
subscribeToGroup(token, meta.mGroupId, true); RsGenExchange::subscribeToGroup(token, meta.mGroupId, true);
else if(shoudlUnSubscribe) else if(shoudlUnSubscribe)
subscribeToGroup(token, meta.mGroupId, false); RsGenExchange::subscribeToGroup(token, meta.mGroupId, false);
#ifdef GXS_MAIL_GRP_DEBUG #ifdef GXS_MAIL_GRP_DEBUG
char buff[30]; char buff[30];
@ -337,7 +369,7 @@ void p3GxsTrans::notifyChanges(std::vector<RsGxsNotify*>& changes)
std::cout << "p3GxsTrans::notifyChanges(...) msgChange" << std::endl; std::cout << "p3GxsTrans::notifyChanges(...) msgChange" << std::endl;
uint32_t token; uint32_t token;
RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
getTokenService()->requestMsgInfo( token, 0xcaca, RsGenExchange::getTokenService()->requestMsgInfo( token, 0xcaca,
opts, msgChange->msgChangeMap ); opts, msgChange->msgChangeMap );
GxsTokenQueue::queueRequest(token, MAILS_UPDATE); GxsTokenQueue::queueRequest(token, MAILS_UPDATE);
@ -393,8 +425,8 @@ bool p3GxsTrans::requestGroupsData(const std::list<RsGxsGroupId>* groupIds)
// std::cout << "p3GxsTrans::requestGroupsList()" << std::endl; // std::cout << "p3GxsTrans::requestGroupsList()" << std::endl;
uint32_t token; uint32_t token;
RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
if(!groupIds) getTokenService()->requestGroupInfo(token, 0xcaca, opts); if(!groupIds) RsGenExchange::getTokenService()->requestGroupInfo(token, 0xcaca, opts);
else getTokenService()->requestGroupInfo(token, 0xcaca, opts, *groupIds); else RsGenExchange::getTokenService()->requestGroupInfo(token, 0xcaca, opts, *groupIds);
GxsTokenQueue::queueRequest(token, GROUPS_LIST); GxsTokenQueue::queueRequest(token, GROUPS_LIST);
return true; return true;
} }

View file

@ -26,6 +26,7 @@
#include "gxstrans/p3gxstransitems.h" #include "gxstrans/p3gxstransitems.h"
#include "services/p3idservice.h" // For p3IdService #include "services/p3idservice.h" // For p3IdService
#include "util/rsthreads.h" #include "util/rsthreads.h"
#include "retroshare/rsgxstrans.h"
struct p3GxsTrans; struct p3GxsTrans;
@ -76,18 +77,32 @@ struct GxsTransClient
* @see GxsTransClient::receiveGxsTransMail(...), * @see GxsTransClient::receiveGxsTransMail(...),
* @see GxsTransClient::notifyGxsTransSendStatus(...). * @see GxsTransClient::notifyGxsTransSendStatus(...).
*/ */
struct p3GxsTrans : RsGenExchange, GxsTokenQueue, p3Config class p3GxsTrans : public RsGenExchange, public GxsTokenQueue, public p3Config, public RsGxsTrans
{ {
public:
p3GxsTrans( RsGeneralDataService* gds, RsNetworkExchangeService* nes, p3GxsTrans( RsGeneralDataService* gds, RsNetworkExchangeService* nes,
p3IdService& identities ) : p3IdService& identities ) :
RsGenExchange( gds, nes, new RsGxsTransSerializer(), RsGenExchange( gds, nes, new RsGxsTransSerializer(),
RS_SERVICE_TYPE_GXS_TRANS, &identities, RS_SERVICE_TYPE_GXS_TRANS, &identities,
AuthenPolicy(), GXS_STORAGE_PERIOD ), AuthenPolicy(), GXS_STORAGE_PERIOD ),
GxsTokenQueue(this), mIdService(identities), GxsTokenQueue(this),
RsGxsTrans(this),
mIdService(identities),
mServClientsMutex("p3GxsTrans client services map mutex"), mServClientsMutex("p3GxsTrans client services map mutex"),
mOutgoingMutex("p3GxsTrans outgoing queue map mutex"), mOutgoingMutex("p3GxsTrans outgoing queue map mutex"),
mIngoingMutex("p3GxsTrans ingoing 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 * 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/rsbaseserial.h"
#include "serialiser/rstlvidset.h" #include "serialiser/rstlvidset.h"
#include "retroshare/rsgxsflags.h" #include "retroshare/rsgxsflags.h"
#include "retroshare/rsgxstrans.h"
#include "retroshare/rsgxscircles.h" // For: GXS_CIRCLE_TYPE_PUBLIC #include "retroshare/rsgxscircles.h" // For: GXS_CIRCLE_TYPE_PUBLIC
#include "services/p3idservice.h" #include "services/p3idservice.h"
#include "serialiser/rstypeserializer.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 struct RsNxsTransPresignedReceipt : RsNxsMsg
{ {
RsNxsTransPresignedReceipt() : RsNxsMsg(RS_SERVICE_TYPE_GXS_TRANS) {} RsNxsTransPresignedReceipt() : RsNxsMsg(RS_SERVICE_TYPE_GXS_TRANS) {}
@ -188,27 +169,6 @@ struct RsGxsTransGroupItem : RsGxsGrpItem
{ return out; } { 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; class RsGxsTransSerializer;
struct OutgoingRecord : RsItem struct OutgoingRecord : RsItem
{ {

View file

@ -60,6 +60,8 @@ public:
public: public:
RsMsgMetaData mMeta; RsMsgMetaData mMeta;
std::set<RsGxsMessageId> mOlderVersions ;
std::string mMsg; // UTF8 encoded. std::string mMsg; // UTF8 encoded.
std::list<RsGxsFile> mFiles; 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; rsPosted = mPosted;
rsGxsForums = mGxsForums; rsGxsForums = mGxsForums;
rsGxsChannels = mGxsChannels; rsGxsChannels = mGxsChannels;
rsGxsTrans = mGxsTrans;
//rsPhoto = mPhoto; //rsPhoto = mPhoto;
//rsWire = mWire; //rsWire = mWire;

View file

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

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>533</width> <width>520</width>
<height>544</height> <height>611</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -34,13 +34,16 @@
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
<widget class="QFrame" name="frame"> <widget class="QFrame" name="profileframe">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::StyledPanel</enum> <enum>QFrame::StyledPanel</enum>
</property> </property>
@ -48,6 +51,9 @@
<enum>QFrame::Raised</enum> <enum>QFrame::Raised</enum>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>9</number>
</property>
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
@ -105,19 +111,63 @@
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QFrame" name="profile_frame"> <widget class="QGroupBox" name="profile_groupBox">
<property name="styleSheet"> <property name="styleSheet">
<string notr="true"/> <string notr="true"/>
</property> </property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout"> <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"> <item row="0" column="0">
<layout class="QGridLayout" name="profilGLayout"> <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"> <item row="7" column="3">
<widget class="QLabel" name="password_check_LB"> <widget class="QLabel" name="password_check_LB">
<property name="text"> <property name="text">
@ -125,17 +175,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="15" column="0"> <item row="8" column="2">
<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">
<widget class="QLineEdit" name="password_input_2"> <widget class="QLineEdit" name="password_input_2">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
@ -163,42 +203,6 @@
</property> </property>
</widget> </widget>
</item> </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"> <item row="18" column="2">
<widget class="QProgressBar" name="entropy_bar"> <widget class="QProgressBar" name="entropy_bar">
<property name="sizePolicy"> <property name="sizePolicy">
@ -229,7 +233,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="16" column="2"> <item row="15" column="2">
<widget class="QComboBox" name="nodeType_CB"> <widget class="QComboBox" name="nodeType_CB">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -271,16 +275,6 @@
</property> </property>
</widget> </widget>
</item> </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"> <item row="4" column="3">
<widget class="QLabel" name="profile_name_check_LB"> <widget class="QLabel" name="profile_name_check_LB">
<property name="text"> <property name="text">
@ -365,7 +359,7 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="9" column="3"> <item row="8" column="3">
<widget class="QLabel" name="password2_check_LB"> <widget class="QLabel" name="password2_check_LB">
<property name="text"> <property name="text">
<string/> <string/>
@ -394,46 +388,6 @@
</property> </property>
</widget> </widget>
</item> </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"> <item row="17" column="2">
<layout class="QHBoxLayout" name="hiddenInfoHLayout"> <layout class="QHBoxLayout" name="hiddenInfoHLayout">
<property name="spacing"> <property name="spacing">
@ -498,20 +452,7 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="10" column="0"> <item row="9" column="2">
<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">
<widget class="QLineEdit" name="nickname_input"> <widget class="QLineEdit" name="nickname_input">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -564,6 +505,191 @@
</property> </property>
</widget> </widget>
</item> </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> </layout>
</item> </item>
</layout> </layout>

View file

@ -1403,7 +1403,7 @@ void NewsFeed::openChat(const RsPeerId &peerId)
ChatDialog::chatFriend(ChatId(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 << "NewsFeed::openComments() Not Handled Yet";
std::cerr << std::endl; std::cerr << std::endl;

View file

@ -58,7 +58,7 @@ public:
virtual QScrollArea *getScrollArea(); virtual QScrollArea *getScrollArea();
virtual void deleteFeedItem(QWidget *item, uint32_t type); virtual void deleteFeedItem(QWidget *item, uint32_t type);
virtual void openChat(const RsPeerId& peerId); 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 testFeeds(uint notifyFlags);
static void testFeed(FeedNotify *feedNotify); static void testFeed(FeedNotify *feedNotify);

View file

@ -411,7 +411,13 @@ void PostedItem::loadComments()
if (mFeedHolder) if (mFeedHolder)
{ {
QString title = QString::fromUtf8(mPost.mMeta.mMsgName.c_str()); 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; 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() void PostedListWidget::newPost()

View file

@ -52,7 +52,7 @@ public:
virtual QScrollArea *getScrollArea(); virtual QScrollArea *getScrollArea();
virtual void deleteFeedItem(QWidget *item, uint32_t type); virtual void deleteFeedItem(QWidget *item, uint32_t type);
virtual void openChat(const RsPeerId& peerId); 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 */ /* GXS functions */
virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req);

View file

@ -17,6 +17,9 @@
<iconset resource="images.qrc"> <iconset resource="images.qrc">
<normaloff>:/images/logo/logo_32.png</normaloff>:/images/logo/logo_32.png</iconset> <normaloff>:/images/logo/logo_32.png</normaloff>:/images/logo/logo_32.png</iconset>
</property> </property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
@ -31,296 +34,310 @@
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
<layout class="QGridLayout" name="mainGLayout"> <widget class="QFrame" name="loginframe">
<property name="leftMargin"> <property name="autoFillBackground">
<number>0</number> <bool>false</bool>
</property> </property>
<property name="rightMargin"> <property name="styleSheet">
<number>0</number> <string notr="true"/>
</property> </property>
<property name="bottomMargin"> <property name="frameShape">
<number>0</number> <enum>QFrame::StyledPanel</enum>
</property> </property>
<item row="0" column="0" colspan="4"> <layout class="QGridLayout" name="mainGLayout">
<layout class="QGridLayout" name="topGLayout"> <property name="leftMargin">
<item row="0" column="0"> <number>0</number>
<spacer name="horizontalSpacer"> </property>
<property name="orientation"> <property name="topMargin">
<enum>Qt::Horizontal</enum> <number>0</number>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="rightMargin">
<size> <number>0</number>
<width>40</width> </property>
<height>20</height> <property name="bottomMargin">
</size> <number>0</number>
</property> </property>
</spacer> <item row="0" column="0" colspan="4">
</item> <layout class="QGridLayout" name="topGLayout">
<item row="0" column="1"> <item row="0" column="0">
<widget class="QLabel" name="rsTopLogo"> <spacer name="horizontalSpacer">
<property name="minimumSize"> <property name="orientation">
<size> <enum>Qt::Horizontal</enum>
<width>0</width> </property>
<height>0</height> <property name="sizeHint" stdset="0">
</size> <size>
</property> <width>40</width>
<property name="palette"> <height>20</height>
<palette> </size>
<active> </property>
<colorrole role="WindowText"> </spacer>
<brush brushstyle="SolidPattern"> </item>
<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>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QLabel" name="label_8"> <widget class="QLabel" name="rsTopLogo">
<property name="text"> <property name="minimumSize">
<string>Profile - Location:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_9">
<property name="maximumSize">
<size> <size>
<width>22</width> <width>0</width>
<height>22</height> <height>0</height>
</size> </size>
</property> </property>
<property name="text"> <property name="palette">
<string/> <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>
<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"> <property name="font">
<font> <font>
<pointsize>12</pointsize> <pointsize>18</pointsize>
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>Log In</string> <string/>
</property> </property>
<property name="default"> <property name="pixmap">
<bool>true</bool> <pixmap resource="images.qrc">:/images/logo/logo_spash2.png</pixmap>
</property>
<property name="flat">
<bool>false</bool>
</property> </property>
</widget> </widget>
</item> </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> </layout>
</widget> </item>
</item> <item row="1" column="2" rowspan="2">
<item row="3" column="1"> <spacer name="horizontalSpacer_4">
<layout class="QHBoxLayout" name="horizontalLayout"> <property name="orientation">
<item> <enum>Qt::Horizontal</enum>
<spacer name="horizontalSpacer_5"> </property>
<property name="orientation"> <property name="sizeType">
<enum>Qt::Horizontal</enum> <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>
<property name="sizeHint" stdset="0"> <item row="0" column="1">
<size> <widget class="QLabel" name="label_8">
<width>40</width> <property name="text">
<height>20</height> <string>Profile - Location:</string>
</size> </property>
</property> </widget>
</spacer> </item>
</item> <item row="1" column="0">
<item> <widget class="QLabel" name="label_9">
<widget class="QLabel" name="labelProfile"> <property name="maximumSize">
<property name="toolTip"> <size>
<string>Opens a dialog for creating a new profile or <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. adding locations to an existing profile.
The current identities/locations will not be affected.</string> The current identities/locations will not be affected.</string>
</property> </property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true"/> <string notr="true"/>
</property> </property>
<property name="text"> <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; <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; &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; } 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;/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> &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> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
</item> </item>
</layout> </layout>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>

View file

@ -1429,7 +1429,8 @@ void ChatWidget::colorChanged()
void ChatWidget::chooseFont() void ChatWidget::chooseFont()
{ {
bool ok; 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) { if (ok) {
currentFont = font; currentFont = font;
setFont(); setFont();

View file

@ -37,7 +37,7 @@ public:
virtual QScrollArea *getScrollArea() = 0; virtual QScrollArea *getScrollArea() = 0;
virtual void deleteFeedItem(QWidget *item, uint32_t type) = 0; virtual void deleteFeedItem(QWidget *item, uint32_t type) = 0;
virtual void openChat(const RsPeerId& peerId) = 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 // Workaround for QTBUG-3372
void lockLayout(QWidget *feedItem, bool lock); void lockLayout(QWidget *feedItem, bool lock);

View file

@ -35,6 +35,7 @@
#include "util/HandleRichText.h" #include "util/HandleRichText.h"
#include "util/DateTime.h" #include "util/DateTime.h"
#include "util/stringutil.h" #include "util/stringutil.h"
#include "gui/gxschannels/CreateGxsChannelMsg.h"
#include <iostream> #include <iostream>
@ -63,9 +64,25 @@ GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId,
std::cerr << std::endl; std::cerr << std::endl;
#endif #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(); setup();
setGroup(group, false); //setGroup(group, false);
requestGroup();
setPost(post); setPost(post);
requestComment(); requestComment();
} }
@ -127,6 +144,7 @@ void GxsChannelPostItem::setup()
connect(ui->commentButton, SIGNAL(clicked()), this, SLOT(loadComments())); connect(ui->commentButton, SIGNAL(clicked()), this, SLOT(loadComments()));
connect(ui->playButton, SIGNAL(clicked()), this, SLOT(play(void))); 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->copyLinkButton, SIGNAL(clicked()), this, SLOT(copyMessageLink()));
connect(ui->readButton, SIGNAL(toggled(bool)), this, SLOT(readToggled(bool))); connect(ui->readButton, SIGNAL(toggled(bool)), this, SLOT(readToggled(bool)));
@ -166,6 +184,12 @@ bool GxsChannelPostItem::setGroup(const RsGxsChannelGroup &group, bool doFill)
mGroup = group; 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) { if (doFill) {
fill(); fill();
} }
@ -301,7 +325,7 @@ void GxsChannelPostItem::loadComment(const uint32_t &token)
if (comNb == 1) { if (comNb == 1) {
sComButText = sComButText.append("(1)"); sComButText = sComButText.append("(1)");
} else if (comNb > 1) { } else if (comNb > 1) {
sComButText = tr("Comments").append("(%1)").arg(comNb); sComButText = tr("Comments ").append("(%1)").arg(comNb);
} }
ui->commentButton->setText(sComButText); ui->commentButton->setText(sComButText);
} }
@ -690,6 +714,12 @@ void GxsChannelPostItem::download()
updateItem(); updateItem();
} }
void GxsChannelPostItem::edit()
{
CreateGxsChannelMsg *msgDialog = new CreateGxsChannelMsg(mGroup.mMeta.mGroupId,mPost.mMeta.mMsgId);
msgDialog->show();
}
void GxsChannelPostItem::play() void GxsChannelPostItem::play()
{ {
std::list<SubFileItem *>::iterator it; std::list<SubFileItem *>::iterator it;

View file

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

View file

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

View file

@ -97,11 +97,12 @@ SubFileItem::SubFileItem(const RsFileHash &hash, const std::string &name, const
void SubFileItem::Setup() void SubFileItem::Setup()
{ {
connect( playButton, SIGNAL( clicked( void ) ), this, SLOT( play ( void ) ) ); connect( playButton, SIGNAL( clicked( ) ), this, SLOT( play ( ) ) );
connect( downloadButton, SIGNAL( clicked( void ) ), this, SLOT( download ( void ) ) ); connect( downloadButton, SIGNAL( clicked( ) ), this, SLOT( download ( ) ) );
connect( cancelButton, SIGNAL( clicked( void ) ), this, SLOT( cancel ( void ) ) ); connect( cancelButton, SIGNAL( clicked( ) ), this, SLOT( cancel( ) ) );
connect( copyLinkButton, SIGNAL( clicked( void ) ), this, SLOT( copyLink ( void ) ) ); connect( deleteButton, SIGNAL( clicked( ) ), this, SLOT( del( ) ) );
connect( saveButton, SIGNAL( clicked( void ) ), this, SLOT( save ( void ) ) ); connect( copyLinkButton, SIGNAL( clicked( ) ), this, SLOT( copyLink ( ) ) );
connect( saveButton, SIGNAL( clicked( ) ), this, SLOT( save ( ) ) );
/* once off check - if remote, check if we have it /* once off check - if remote, check if we have it
* NB: This check might be expensive - and it'll happen often! * 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(); smaller();
updateItemStatic(); updateItemStatic();
updateItem(); updateItem();
} }
void SubFileItem::del()
{
emit wantsToBeDeleted();
}
bool SubFileItem::done() bool SubFileItem::done()
{ {
return (mMode >= SFI_STATE_LOCAL); return (mMode >= SFI_STATE_LOCAL);
@ -176,7 +186,7 @@ void SubFileItem::updateItemStatic()
} }
/* get full path for local file */ /* 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 #ifdef DEBUG_ITEM
std::cerr << "SubFileItem::updateItemStatic() STATE=Local/Upload checking path"; std::cerr << "SubFileItem::updateItemStatic() STATE=Local/Upload checking path";
@ -190,7 +200,10 @@ void SubFileItem::updateItemStatic()
/* look up path */ /* look up path */
if (!rsFiles->FileDetails(mFileHash, hintflags, fi)) 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 #ifdef DEBUG_ITEM
std::cerr << "SubFileItem::updateItemStatic() STATE=>Error No Details"; std::cerr << "SubFileItem::updateItemStatic() STATE=>Error No Details";
std::cerr << std::endl; std::cerr << std::endl;
@ -241,6 +254,7 @@ void SubFileItem::updateItemStatic()
case SFI_STATE_REMOTE: case SFI_STATE_REMOTE:
playButton->setEnabled(false); playButton->setEnabled(false);
downloadButton->setEnabled(true); downloadButton->setEnabled(true);
downloadButton->setVisible(true);
cancelButton->setEnabled(false); cancelButton->setEnabled(false);
progressBar->setValue(0); 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_CHANNEL = 0x0010;
const uint32_t SFI_TYPE_ATTACH = 0x0020; 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 //! This create a gui widget that allows users to access files shared by user
@ -86,10 +88,14 @@ private slots:
void toggle(); void toggle();
void cancel(); void cancel();
void del();
void save(); void save();
void updateItem(); void updateItem();
signals:
void wantsToBeDeleted();
private: private:
void Setup(); void Setup();

View file

@ -6,12 +6,21 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>464</width> <width>547</width>
<height>71</height> <height>128</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout_4"> <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> <number>0</number>
</property> </property>
<property name="spacing"> <property name="spacing">
@ -26,27 +35,6 @@
<enum>QFrame::Sunken</enum> <enum>QFrame::Sunken</enum>
</property> </property>
<layout class="QGridLayout" name="gridLayout_2"> <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"> <item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
@ -210,6 +198,41 @@
</property> </property>
</widget> </widget>
</item> </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> </layout>
</item> </item>
</layout> </layout>

View file

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

View file

@ -40,7 +40,7 @@ public:
GxsCommentContainer(QWidget *parent = 0); GxsCommentContainer(QWidget *parent = 0);
void setup(); 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 GxsServiceDialog *createServiceDialog() = 0;
virtual QString getServiceName() = 0; virtual QString getServiceName() = 0;
@ -67,9 +67,9 @@ public:
virtual ~GxsServiceDialog() { return; } 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: private:

View file

@ -59,20 +59,16 @@ GxsCommentDialog::~GxsCommentDialog()
delete(ui); 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; std::cerr << std::endl;
mGrpId = grpId; mGrpId = grpId;
mMsgId = msgId; mMostRecentMsgId = most_recent_msgId;
mMsgVersions = msg_versions;
RsGxsGrpMsgIdPair threadId; ui->treeWidget->requestComments(mGrpId,msg_versions,most_recent_msgId);
threadId.first = grpId;
threadId.second = msgId;
ui->treeWidget->requestComments(threadId);
} }
void GxsCommentDialog::refresh() void GxsCommentDialog::refresh()
@ -80,7 +76,7 @@ void GxsCommentDialog::refresh()
std::cerr << "GxsCommentDialog::refresh()"; std::cerr << "GxsCommentDialog::refresh()";
std::cerr << std::endl; std::cerr << std::endl;
commentLoad(mGrpId, mMsgId); commentLoad(mGrpId, mMsgVersions,mMostRecentMsgId);
} }
void GxsCommentDialog::idChooserReady() void GxsCommentDialog::idChooserReady()

View file

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

View file

@ -22,8 +22,12 @@
*/ */
#include <QMimeData> #include <QMimeData>
#include <QTextDocument>
#include <QAbstractTextDocumentLayout>
#include <QApplication>
#include <QDateTime> #include <QDateTime>
#include <QMenu> #include <QMenu>
#include <QPainter>
#include "gui/common/RSElidedItemDelegate.h" #include "gui/common/RSElidedItemDelegate.h"
#include "gui/gxs/GxsCommentTreeWidget.h" #include "gui/gxs/GxsCommentTreeWidget.h"
@ -46,11 +50,73 @@
#define COMMENT_VOTE_ACK 0x001234 #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 */ /* Images for context menu icons */
#define IMAGE_MESSAGE ":/images/folder-draft.png" #define IMAGE_MESSAGE ":/images/folder-draft.png"
#define IMAGE_VOTEUP ":/images/vote_up.png" #define IMAGE_VOTEUP ":/images/vote_up.png"
#define IMAGE_VOTEDOWN ":/images/vote_down.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) GxsCommentTreeWidget::GxsCommentTreeWidget(QWidget *parent)
:QTreeWidget(parent), mTokenQueue(NULL), mRsTokenService(NULL), mCommentService(NULL) :QTreeWidget(parent), mTokenQueue(NULL), mRsTokenService(NULL), mCommentService(NULL)
@ -62,6 +128,9 @@ GxsCommentTreeWidget::GxsCommentTreeWidget(QWidget *parent)
itemDelegate->setSpacing(QSize(0, 2)); itemDelegate->setSpacing(QSize(0, 2));
setItemDelegate(itemDelegate); setItemDelegate(itemDelegate);
setWordWrap(true); setWordWrap(true);
setItemDelegateForColumn(PCITEM_COLUMN_COMMENT,new MultiLinesCommentDelegate(QFontMetricsF(font()))) ;
// QFont font = QFont("ARIAL", 10); // QFont font = QFont("ARIAL", 10);
// font.setBold(true); // 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); Q_UNUSED(previous);
if(current) 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 ); QMenu contextMnu( this );
QAction* action = contextMnu.addAction(QIcon(IMAGE_MESSAGE), tr("Reply to Comment"), this, SLOT(replyToComment())); 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 = contextMnu.addAction(QIcon(IMAGE_MESSAGE), tr("Submit Comment"), this, SLOT(makeComment()));
action->setDisabled(mThreadId.first.isNull()); action->setDisabled(mMsgVersions.empty());
contextMnu.addSeparator(); contextMnu.addSeparator();
@ -112,7 +181,7 @@ void GxsCommentTreeWidget::customPopUpMenu(const QPoint& /*point*/)
action->setDisabled(mVoterId.isNull()); action->setDisabled(mVoterId.isNull());
if (!mCurrentMsgId.isNull()) if (!mCurrentCommentMsgId.isNull())
{ {
// not implemented yet // not implemented yet
/* /*
@ -138,7 +207,8 @@ void GxsCommentTreeWidget::voteUp()
{ {
std::cerr << "GxsCommentTreeWidget::voteUp()"; std::cerr << "GxsCommentTreeWidget::voteUp()";
std::cerr << std::endl; 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 << "GxsCommentTreeWidget::voteDown()";
std::cerr << std::endl; std::cerr << std::endl;
vote(mThreadId.first, mThreadId.second, mCurrentMsgId, mVoterId, false);
vote(mGroupId, mLatestMsgId, mCurrentCommentMsgId, mVoterId, false);
} }
void GxsCommentTreeWidget::setVoteId(const RsGxsId &voterId) void GxsCommentTreeWidget::setVoteId(const RsGxsId &voterId)
@ -216,16 +287,16 @@ void GxsCommentTreeWidget::banUser()
void GxsCommentTreeWidget::makeComment() void GxsCommentTreeWidget::makeComment()
{ {
GxsCreateCommentDialog pcc(mTokenQueue, mCommentService, mThreadId, mThreadId.second, this); GxsCreateCommentDialog pcc(mTokenQueue, mCommentService, std::make_pair(mGroupId,mLatestMsgId), mLatestMsgId, this);
pcc.exec(); pcc.exec();
} }
void GxsCommentTreeWidget::replyToComment() void GxsCommentTreeWidget::replyToComment()
{ {
RsGxsGrpMsgIdPair msgId; RsGxsGrpMsgIdPair msgId;
msgId.first = mThreadId.first; msgId.first = mGroupId;
msgId.second = mCurrentMsgId; msgId.second = mCurrentCommentMsgId;
GxsCreateCommentDialog pcc(mTokenQueue, mCommentService, msgId, mThreadId.second, this); GxsCreateCommentDialog pcc(mTokenQueue, mCommentService, msgId, mLatestMsgId, this);
pcc.exec(); pcc.exec();
} }
@ -235,36 +306,44 @@ void GxsCommentTreeWidget::setup(RsTokenService *token_service, RsGxsCommentServ
mCommentService = comment_service; mCommentService = comment_service;
mTokenQueue = new TokenQueue(token_service, this); mTokenQueue = new TokenQueue(token_service, this);
connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customPopUpMenu(QPoint))); 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; return;
} }
/* Load Comments */ /* 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 */ /* request comments */
mThreadId = threadId; mGroupId = group ;
service_requestComments(threadId); 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 */ /* request comments */
std::cerr << "GxsCommentTreeWidget::service_requestComments(" << threadId.second << ")"; std::cerr << "GxsCommentTreeWidget::service_requestComments for group " << group_id << std::endl;
std::cerr << 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; RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA;
opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST; opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST;
std::vector<RsGxsGrpMsgIdPair> msgIds;
msgIds.push_back(threadId);
uint32_t token; 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); 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 << "GxsCommentTreeWidget::completeItems() Added to topLevelItems";
std::cerr << std::endl; std::cerr << std::endl;
@ -391,7 +470,7 @@ void GxsCommentTreeWidget::acknowledgeComment(const uint32_t &token)
mCommentService->acknowledgeComment(token, msgId); mCommentService->acknowledgeComment(token, msgId);
// simply reload data // 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)) if (mCommentService->acknowledgeVote(token, msgId))
{ {
// reload data if vote was added. // 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; RsGxsId authorId = comment.mMeta.mAuthorId;
item->setId(authorId, PCITEM_COLUMN_AUTHOR, false); item->setId(authorId, PCITEM_COLUMN_AUTHOR, false);
item->setData(PCITEM_COLUMN_COMMENT,POST_COLOR_ROLE,QVariant(authorId.toByteArray()[1]));
text = QString::number(comment.mScore); text = QString::number(comment.mScore);
item->setText(PCITEM_COLUMN_SCORE, text); item->setText(PCITEM_COLUMN_SCORE, text);

View file

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

View file

@ -64,7 +64,10 @@ void GxsFeedItem::comments(const QString &title)
if (mFeedHolder) 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.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA;
opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST; opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST;
RsGxsGrpMsgIdPair msgIdPair;
msgIdPair.first = groupId();
msgIdPair.second = messageId();
std::vector<RsGxsGrpMsgIdPair> msgIds; 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; uint32_t token;
mLoadQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeComment); 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); GxsFeedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, RsGxsIfaceHelper *iface, bool autoUpdate);
virtual ~GxsFeedItem(); 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. //To be able to update with thread message when comment is received.
void setMessageId( RsGxsMessageId id) {mMessageId = id;} void setMessageId( RsGxsMessageId id) {mMessageId = id;}
void setMessageVersions( const QVector<RsGxsMessageId>& v) { mMessageVersions = v;}
protected: protected:
/* load message data */ /* load message data */
@ -61,6 +64,7 @@ protected slots:
private: private:
RsGxsMessageId mMessageId; RsGxsMessageId mMessageId;
QVector<RsGxsMessageId> mMessageVersions ;
uint32_t mTokenTypeMessage; uint32_t mTokenTypeMessage;
uint32_t mTokenTypeComment; 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); GxsGroupFeedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, RsGxsIfaceHelper *iface, bool autoUpdate);
virtual ~GxsGroupFeedItem(); virtual ~GxsGroupFeedItem();
RsGxsGroupId groupId() { return mGroupId; } RsGxsGroupId groupId() const { return mGroupId; }
uint32_t feedId() { return mFeedId; } uint32_t feedId() const { return mFeedId; }
protected: protected:
uint32_t nextTokenType() { return ++mNextTokenType; } uint32_t nextTokenType() { return ++mNextTokenType; }

View file

@ -525,7 +525,7 @@ void GxsGroupFrameDialog::sharePublishKey()
shareUi.exec(); 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(); RsGxsCommentService *commentService = getCommentService();
if (!commentService) { if (!commentService) {
@ -533,7 +533,8 @@ void GxsGroupFrameDialog::loadComment(const RsGxsGroupId &grpId, const RsGxsMess
return; return;
} }
GxsCommentDialog *commentDialog = commentWidget(msgId); GxsCommentDialog *commentDialog = commentWidget(most_recent_msgId);
if (!commentDialog) { if (!commentDialog) {
QString comments = title; QString comments = title;
if (title.length() > MAX_COMMENT_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); commentDialog = new GxsCommentDialog(this, mInterface->getTokenService(), commentService);
QWidget *commentHeader = createCommentHeaderWidget(grpId, msgId); QWidget *commentHeader = createCommentHeaderWidget(grpId, most_recent_msgId);
if (commentHeader) { if (commentHeader) {
commentDialog->setCommentHeader(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); int index = ui->messageTabWidget->addTab(commentDialog, comments);
ui->messageTabWidget->setTabIcon(index, QIcon(IMAGE_COMMENT)); 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(groupChanged(QWidget*)), this, SLOT(messageTabInfoChanged(QWidget*)));
connect(msgWidget, SIGNAL(waitingChanged(QWidget*)), this, SLOT(messageTabWaitingChanged(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; return msgWidget;
} }
GxsCommentDialog *GxsGroupFrameDialog::commentWidget(const RsGxsMessageId &msgId) GxsCommentDialog *GxsGroupFrameDialog::commentWidget(const RsGxsMessageId& msgId)
{ {
int tabCount = ui->messageTabWidget->count(); int tabCount = ui->messageTabWidget->count();
for (int index = 0; index < tabCount; ++index) { for (int index = 0; index < tabCount; ++index) {

View file

@ -126,7 +126,7 @@ private slots:
void sharePublishKey(); 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: private:
virtual QString text(TextType type) = 0; virtual QString text(TextType type) = 0;

View file

@ -54,7 +54,7 @@ public:
signals: signals:
void groupChanged(QWidget *widget); void groupChanged(QWidget *widget);
void waitingChanged(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: protected:
virtual void setAllMessagesReadDo(bool read, uint32_t &token) = 0; virtual void setAllMessagesReadDo(bool read, uint32_t &token) = 0;

View file

@ -38,11 +38,15 @@
//#define ENABLE_GENERATE //#define ENABLE_GENERATE
#define CREATEMSG_CHANNELINFO 0x002 #define CREATEMSG_CHANNELINFO 0x002
#define CREATEMSG_CHANNEL_POST_INFO 0x003
// #define DEBUG_CREATE_GXS_MSG
/** Constructor */ /** Constructor */
CreateGxsChannelMsg::CreateGxsChannelMsg(const RsGxsGroupId &cId) CreateGxsChannelMsg::CreateGxsChannelMsg(const RsGxsGroupId &cId, RsGxsMessageId existing_post)
: QDialog (NULL, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint), mChannelId(cId) ,mCheckAttachment(true), mAutoMediaThumbNail(false) : 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 */ /* Invoke the Qt Designer generated object setup routine */
setupUi(this); setupUi(this);
@ -50,7 +54,11 @@ CreateGxsChannelMsg::CreateGxsChannelMsg(const RsGxsGroupId &cId)
mChannelQueue = new TokenQueue(rsGxsChannels->getTokenService(), this); mChannelQueue = new TokenQueue(rsGxsChannels->getTokenService(), this);
headerFrame->setHeaderImage(QPixmap(":/images/channels.png")); 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 ); 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 */ /* add a SubFileItem to the attachment section */
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::addAttachment()"; std::cerr << "CreateGxsChannelMsg::addAttachment()";
std::cerr << std::endl; std::cerr << std::endl;
#endif
/* add widget in for new destination */ /* 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) if (local)
{
flags |= SFI_STATE_LOCAL; flags |= SFI_STATE_LOCAL;
}
else else
{
flags |= SFI_STATE_REMOTE; flags |= SFI_STATE_REMOTE;
}
SubFileItem *file = new SubFileItem(hash, fname, "", size, flags, srcId); // destroyed when fileFrame (this subfileitem) is destroyed 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); mAttachments.push_back(file);
QLayout *layout = fileFrame->layout(); QLayout *layout = fileFrame->layout();
layout->addWidget(file); layout->addWidget(file);
if (mCheckAttachment) if (mCheckAttachment)
{
checkAttachmentReady(); 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() void CreateGxsChannelMsg::addExtraFile()
{ {
/* add a SubFileItem to the attachment section */ /* add a SubFileItem to the attachment section */
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::addExtraFile() opening file dialog"; std::cerr << "CreateGxsChannelMsg::addExtraFile() opening file dialog";
std::cerr << std::endl; std::cerr << std::endl;
#endif
QStringList files; QStringList files;
if (misc::getOpenFileNames(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", 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) void CreateGxsChannelMsg::addAttachment(const std::string &path)
{ {
/* add a SubFileItem to the attachment section */ /* add a SubFileItem to the attachment section */
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::addAttachment()"; std::cerr << "CreateGxsChannelMsg::addAttachment()";
std::cerr << std::endl; std::cerr << std::endl;
#endif
if(mAutoMediaThumbNail) if(mAutoMediaThumbNail)
setThumbNail(path, 2000); setThumbNail(path, 2000);
@ -522,8 +552,10 @@ void CreateGxsChannelMsg::checkAttachmentReady()
void CreateGxsChannelMsg::cancelMsg() void CreateGxsChannelMsg::cancelMsg()
{ {
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::cancelMsg() :" std::cerr << "CreateGxsChannelMsg::cancelMsg() :"
<< "Deleting EXTRA attachments" << std::endl; << "Deleting EXTRA attachments" << std::endl;
#endif
std::cerr << std::endl; std::cerr << std::endl;
@ -555,6 +587,15 @@ void CreateGxsChannelMsg::newChannelMsg()
uint32_t token; uint32_t token;
mChannelQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, groupIds, CREATEMSG_CHANNELINFO); 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() void CreateGxsChannelMsg::sendMsg()
{ {
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::sendMsg()"; std::cerr << "CreateGxsChannelMsg::sendMsg()";
std::cerr << std::endl; std::cerr << std::endl;
#endif
/* construct message bits */ /* construct message bits */
std::string subject = std::string(misc::removeNewLine(subjectEdit->text()).toUtf8()); 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.mThreadId.clear() ;
post.mMeta.mMsgId.clear() ; post.mMeta.mMsgId.clear() ;
post.mMeta.mOrigMsgId = mOrigPostId;
post.mMeta.mMsgName = subject; post.mMeta.mMsgName = subject;
post.mMsg = msg; post.mMsg = msg;
post.mFiles = files; post.mFiles = files;
@ -686,10 +730,47 @@ void CreateGxsChannelMsg::addThumbnail()
thumbnail_label->setPixmap(picture); 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) void CreateGxsChannelMsg::loadChannelInfo(const uint32_t &token)
{ {
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::loadChannelInfo()"; std::cerr << "CreateGxsChannelMsg::loadChannelInfo()";
std::cerr << std::endl; std::cerr << std::endl;
#endif
std::list<RsGroupMetaData> groupInfo; std::list<RsGroupMetaData> groupInfo;
rsGxsChannels->getGroupSummary(token, 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) void CreateGxsChannelMsg::loadRequest(const TokenQueue *queue, const TokenRequest &req)
{ {
#ifdef DEBUG_CREATE_GXS_MSG
std::cerr << "CreateGxsChannelMsg::loadRequest() UserType: " << req.mUserType; std::cerr << "CreateGxsChannelMsg::loadRequest() UserType: " << req.mUserType;
std::cerr << std::endl; std::cerr << std::endl;
#endif
if (queue == mChannelQueue) if (queue == mChannelQueue)
{ {
@ -719,6 +802,9 @@ void CreateGxsChannelMsg::loadRequest(const TokenQueue *queue, const TokenReques
case CREATEMSG_CHANNELINFO: case CREATEMSG_CHANNELINFO:
loadChannelInfo(req.mToken); loadChannelInfo(req.mToken);
break; break;
case CREATEMSG_CHANNEL_POST_INFO:
loadChannelPostInfo(req.mToken);
break;
default: default:
std::cerr << "CreateGxsChannelMsg::loadRequest() UNKNOWN UserType "; std::cerr << "CreateGxsChannelMsg::loadRequest() UNKNOWN UserType ";
std::cerr << std::endl; std::cerr << std::endl;

View file

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

View file

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

View file

@ -207,9 +207,9 @@ void GxsChannelPostsWidget::openChat(const RsPeerId & /*peerId*/)
} }
// Callback from Widget->FeedHolder->ServiceDialog->CommentContainer->CommentDialog, // 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() void GxsChannelPostsWidget::createMsg()
@ -398,7 +398,27 @@ void GxsChannelPostsWidget::filterChanged(int filter)
void GxsChannelPostsWidget::createPostItem(const RsGxsChannelPost &post, bool related) void GxsChannelPostsWidget::createPostItem(const RsGxsChannelPost &post, bool related)
{ {
GxsChannelPostItem *item = NULL; 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); FeedItem *feedItem = ui->feedWidget->findGxsFeedItem(post.mMeta.mGroupId, post.mMeta.mMsgId);
item = dynamic_cast<GxsChannelPostItem*>(feedItem); item = dynamic_cast<GxsChannelPostItem*>(feedItem);
} }
@ -438,8 +458,6 @@ void GxsChannelPostsWidget::insertChannelPosts(std::vector<RsGxsChannelPost> &po
return; return;
} }
std::vector<RsGxsChannelPost>::const_reverse_iterator it;
int count = posts.size(); int count = posts.size();
int pos = 0; int pos = 0;
@ -447,18 +465,127 @@ void GxsChannelPostsWidget::insertChannelPosts(std::vector<RsGxsChannelPost> &po
ui->feedWidget->setSortingEnabled(false); ui->feedWidget->setSortingEnabled(false);
} }
for (it = posts.rbegin(); it != posts.rend(); ++it) // collect new versions of posts if any
{
if (thread && thread->stopped()) {
break;
}
if (thread) { #ifdef DEBUG_CHANNEL
thread->emitAddPost(qVariantFromValue(*it), related, ++pos, count); std::cerr << "Inserting channel posts" << std::endl;
} else { #endif
createPostItem(*it, related);
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) { if (!thread) {
ui->feedWidget->setSortingEnabled(true); ui->feedWidget->setSortingEnabled(true);

View file

@ -61,7 +61,7 @@ public:
virtual QScrollArea *getScrollArea(); virtual QScrollArea *getScrollArea();
virtual void deleteFeedItem(QWidget *item, uint32_t type); virtual void deleteFeedItem(QWidget *item, uint32_t type);
virtual void openChat(const RsPeerId& peerId); 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: protected:
/* GxsMessageFramePostWidget */ /* GxsMessageFramePostWidget */

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>793</width> <width>880</width>
<height>465</height> <height>557</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <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; <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; &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; } 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> &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>
<property name="textInteractionFlags"> <property name="textInteractionFlags">

View file

@ -1,5 +1,7 @@
<RCC> <RCC>
<qresource prefix="/"> <qresource prefix="/">
<file>icons/svg/hidden.svg</file>
<file>icons/svg/randomness.svg</file>
<file>icons/svg/password.svg</file> <file>icons/svg/password.svg</file>
<file>icons/stars/star0.png</file> <file>icons/stars/star0.png</file>
<file>icons/stars/star1.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> <RCC>
<qresource prefix="/"> <qresource prefix="/">
<file>images/logo/background.png</file>
<file>images/logo/logo_spash2.png</file> <file>images/logo/logo_spash2.png</file>
<file>images/network_map.png</file> <file>images/network_map.png</file>
<file>images/global_switch_on.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); background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2);
} }
GenCertDialog QComboBox#genPGPuser { GenCertDialog QComboBox#genPGPuser {
border: 4px solid #0099cc; border: 2px solid #0099cc;
border-radius: 6px; border-radius: 6px;
background: white; background: white;
font: bold; font: bold;
} }
GenCertDialog QSpinBox#hiddenport_spinBox { GenCertDialog QSpinBox#hiddenport_spinBox {
border: 4px solid #0099cc; border: 2px solid #0099cc;
border-radius: 6px; border-radius: 6px;
background: white; background: white;
font: bold; font: bold;
} }
GenCertDialog QLineEdit#hiddenaddr_input { GenCertDialog QLineEdit#hiddenaddr_input {
border: 4px solid #0099cc; border: 2px solid #0099cc;
border-radius: 6px; border-radius: 6px;
background: white; background: white;
font: bold; font: bold;
} }
GenCertDialog QLineEdit#password_input_2 { GenCertDialog QLineEdit#password_input_2 {
border: 4px solid #0099cc; border: 2px solid #0099cc;
border-radius: 6px; border-radius: 6px;
background: white; background: white;
font: bold; font: bold;
} }
GenCertDialog QLineEdit#password_input { GenCertDialog QLineEdit#password_input {
border: 4px solid #0099cc; border: 2px solid #0099cc;
border-radius: 6px; border-radius: 6px;
background: white; background: white;
font: bold; font: bold;
} }
GenCertDialog QLineEdit#nickname_input { GenCertDialog QLineEdit#nickname_input {
border: 4px solid #0099cc; border: 2px solid #0099cc;
border-radius: 6px; border-radius: 6px;
background: white; background: white;
font: bold; font: bold;
} }
GenCertDialog QLineEdit#node_input { GenCertDialog QLineEdit#node_input {
border: 4px solid #0099cc; border: 2px solid #0099cc;
border-radius: 6px; border-radius: 6px;
background: white; background: white;
font: bold; font: bold;
} }
GenCertDialog QLineEdit#name_input { GenCertDialog QLineEdit#name_input {
border: 4px solid #0099cc; border: 2px solid #0099cc;
border-radius: 6px; border-radius: 6px;
background: white; background: white;
font: bold; font: bold;
@ -773,3 +773,13 @@ StartDialog QPushButton#loadButton {
StartDialog QPushButton#loadButton:hover { StartDialog QPushButton#loadButton:hover {
border-image: url(:/images/btn_blue_hover.png) 4; 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() void ChatPage::on_pushButtonChangeChatFont_clicked()
{ {
bool ok; 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) { if (ok) {
fontTempChat = font; fontTempChat = font;
// using fontTempChat.rawname() does not always work! // using fontTempChat.rawname() does not always work!
@ -424,6 +424,7 @@ void ChatPage::on_pushButtonChangeChatFont_clicked()
QStringList fontname = fontTempChat.toString().split(","); QStringList fontname = fontTempChat.toString().split(",");
ui.labelChatFontPreview->setText(fontname[0]); ui.labelChatFontPreview->setText(fontname[0]);
ui.labelChatFontPreview->setFont(fontTempChat); ui.labelChatFontPreview->setFont(fontTempChat);
updateChatParams();
} }
} }

View file

@ -14,7 +14,7 @@
<item row="3" column="0"> <item row="3" column="0">
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>2</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="general"> <widget class="QWidget" name="general">
<attribute name="title"> <attribute name="title">
@ -866,7 +866,7 @@
<enum>QTabWidget::North</enum> <enum>QTabWidget::North</enum>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>2</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="publicTab"> <widget class="QWidget" name="publicTab">
<attribute name="title"> <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/TurtleRouterStatistics.h>
#include <gui/statistics/GlobalRouterStatistics.h> #include <gui/statistics/GlobalRouterStatistics.h>
#include <gui/statistics/GxsTransportStatistics.h>
#include <gui/statistics/BwCtrlWindow.h> #include <gui/statistics/BwCtrlWindow.h>
#include <gui/statistics/DhtWindow.h> #include <gui/statistics/DhtWindow.h>
@ -50,10 +51,10 @@
#define IMAGE_DHT ":/images/dht32.png" #define IMAGE_DHT ":/images/dht32.png"
#define IMAGE_TURTLE ":images/turtle.png" #define IMAGE_TURTLE ":images/turtle.png"
#define IMAGE_BWGRAPH ":/images/ksysguard.png" #define IMAGE_BWGRAPH ":/images/ksysguard.png"
#define IMAGE_GLOBALROUTER ":/images/network32.png" #define IMAGE_GLOBALROUTER ":/images/network32.png"
#define IMAGE_BANDWIDTH ":images/office-chart-area-stacked.png" #define IMAGE_BANDWIDTH ":images/office-chart-area-stacked.png"
#define IMAGE_RTT ":images/office-chart-line.png" #define IMAGE_RTT ":images/office-chart-line.png"
/********************************************** STATIC WINDOW *************************************/ /********************************************** STATIC WINDOW *************************************/
StatisticsWindow * StatisticsWindow::mInstance = NULL; StatisticsWindow * StatisticsWindow::mInstance = NULL;
@ -133,6 +134,9 @@ void StatisticsWindow::initStackedPage()
ui->stackPages->add(grsdlg = new GlobalRouterStatistics(ui->stackPages), ui->stackPages->add(grsdlg = new GlobalRouterStatistics(ui->stackPages),
action = createPageAction(QIcon(IMAGE_GLOBALROUTER), tr("Global Router"), grp)); 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), ui->stackPages->add(rttdlg = new RttStatistics(ui->stackPages),
action = createPageAction(QIcon(IMAGE_RTT), tr("RTT Statistics"), grp)); action = createPageAction(QIcon(IMAGE_RTT), tr("RTT Statistics"), grp));

View file

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

View file

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