merged upstream/master

This commit is contained in:
csoler 2020-02-17 19:54:16 +01:00
commit 167380127b
No known key found for this signature in database
GPG Key ID: 7BCA522266C0804C
80 changed files with 1225 additions and 782 deletions

View File

@ -9,28 +9,28 @@ RetroShare provides filesharing, chat, messages, forums, channels and more.
.Build Status .Build Status
|=============================================================================== |===============================================================================
|GNU/Linux, MacOS, (via travis-ci) | image:https://travis-ci.org/RetroShare/RetroShare.svg?branch=master[link="https://travis-ci.org/RetroShare/RetroShare"] |GNU/Linux, macOS, (via Travis CI) | image:https://travis-ci.org/RetroShare/RetroShare.svg?branch=master[link="https://travis-ci.org/RetroShare/RetroShare"]
|Windows (via appveyor) | image:https://ci.appveyor.com/api/projects/status/github/RetroShare/RetroShare?svg=true[link="https://ci.appveyor.com/project/RetroShare58622/retroshare"] |Windows (via AppVeyor) | image:https://ci.appveyor.com/api/projects/status/github/RetroShare/RetroShare?svg=true[link="https://ci.appveyor.com/project/RetroShare58622/retroshare"]
|=============================================================================== |===============================================================================
== Compilation == Compilation
It is very difficult to keep a comprehensive (we support many platforms) and Short of comprehensive and updated documentation on how to build RetroShare
updated documentation on how to build RetroShare, instead we provide scripts and (for the many supported platforms it runs on), scripts and recipes are provided
recipes that are used to create the packages for the supported platforms and in the aim of creating packages for the supported platforms (and more)
more in the `build_scripts` directory of this repository. in the `build_scripts` directory of this repository.
Those packaging receipts together with the continuous integration files Those packaging receipts together with the continuous integration files
`.travis.yml` and `appveyor.yml` are a good source of knowledge on how to `.travis.yml` and `appveyor.yml` are a good source of knowledge on how to
compile RetroShare on different platforms. compile RetroShare on different platforms.
== Using RetroShare on a headless computer with WebUI == Using RetroShare on a headless computer with web UI
WARNING: This section is outdated need to be adapted to new WebUI WARNING: This section is outdated need to be adapted to the new web UI
The webUI needs to be enabled as a parameter option in retroshare-service: The web UI needs to be enabled as a parameter option to the retroshare-service:
[source,bash] [source,bash]
-------- --------
@ -40,16 +40,16 @@ The webUI needs to be enabled as a parameter option in retroshare-service:
The web UI is only accessible on localhost:9090. It is advised to keep it that way so that your RS The web UI is only accessible on localhost:9090. It is advised to keep it that way so that your RS
cannot be controlled using an untrusted connection. cannot be controlled using an untrusted connection.
To access your web UI from a distance, just open a SSH tunnel on it: To access your web UI from a distance, just open a SSH tunnel to it:
[source,bash] [source,bash]
-------- --------
distant_machine:~/ > ssh rs_host -L 9090:localhost:9090 -N distant_machine:~/ > ssh rs_host -L 9090:localhost:9090 -N
-------- --------
"rs_host" is the machine running retroshare-nogui. Then on the distant machine, access your webUI on "rs_host" is the machine running `retroshare-nogui`. Then on the distant machine, access your web UI on
http://localhost:9090 http://localhost:9090
That also works with a retroshare GUI of course. (This can also be done from the RetroShare GUI.)

View File

@ -12,10 +12,6 @@ DESTDIR = lib
!include("use_libretroshare.pri"):error("Including") !include("use_libretroshare.pri"):error("Including")
# the dht stunner is used to obtain RS external ip addr. when it is natted
# this system is unreliable and rs supports a newer and better one (asking connected peers)
# CONFIG += useDhtStunner
# treat warnings as error for better removing # treat warnings as error for better removing
#QMAKE_CFLAGS += -Werror #QMAKE_CFLAGS += -Werror
#QMAKE_CXXFLAGS += -Werror #QMAKE_CXXFLAGS += -Werror

View File

@ -711,47 +711,6 @@ void p3NetMgrIMPL::netExtCheck()
} }
} }
#ifdef ALLOW_DHT_STUNNER
// (cyril) I disabled this because it's pretty dangerous. The DHT can report a wrong address quite easily
// if the other DHT peers are not collaborating.
/* Next ask the DhtStunner */
{
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Not Ok, Checking DhtStunner" << std::endl;
#endif
uint8_t isstable = 0;
struct sockaddr_storage tmpaddr;
sockaddr_storage_clear(tmpaddr);
if (mDhtStunner)
{
/* input network bits */
if (mDhtStunner->getExternalAddr(tmpaddr, isstable))
{
if((rsBanList == NULL) || rsBanList->isAddressAccepted(tmpaddr,RSBANLIST_CHECKING_FLAGS_BLACKLIST))
{
// must be stable???
isStable = (isstable == 1);
//mNetFlags.mExtAddr = tmpaddr;
mNetFlags.mExtAddrOk = true;
mNetFlags.mExtAddrStableOk = isStable;
address_votes[tmpaddr].n++ ;
#ifdef NETMGR_DEBUG_STATEBOX
std::cerr << "p3NetMgrIMPL::netExtCheck() From DhtStunner: ";
std::cerr << sockaddr_storage_tostring(tmpaddr);
std::cerr << " Stable: " << (uint32_t) isstable;
std::cerr << std::endl;
#endif
}
else
std::cerr << "(SS) DHTStunner returned wrong own IP " << sockaddr_storage_iptostring(tmpaddr) << " (banned). Rejecting." << std::endl;
}
}
}
#endif
/* ask ExtAddrFinder */ /* ask ExtAddrFinder */
{ {
/* ExtAddrFinder */ /* ExtAddrFinder */
@ -829,6 +788,49 @@ void p3NetMgrIMPL::netExtCheck()
#endif #endif
} }
#ifdef ALLOW_DHT_STUNNER
// (cyril) I disabled this because it's pretty dangerous. The DHT can report a wrong address quite easily
// if the other DHT peers are not collaborating.
// (sehraf) For the record: The udp stunner uses multiple (as for now: two) peers to ensure that the IP recieved is the correct one, see UdpStunner::locked_checkExternalAddress()
// Nevertheless this stays a more risky method to determine the external ip address.
/* lastly ask the DhtStunner as fallback */
if (address_votes.empty()) {
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Not Ok, Checking DhtStunner" << std::endl;
#endif
uint8_t isstable = 0;
struct sockaddr_storage tmpaddr;
sockaddr_storage_clear(tmpaddr);
if (mDhtStunner)
{
/* input network bits */
if (mDhtStunner->getExternalAddr(tmpaddr, isstable))
{
if((rsBanList == NULL) || rsBanList->isAddressAccepted(tmpaddr,RSBANLIST_CHECKING_FLAGS_BLACKLIST))
{
// must be stable???
isStable = (isstable == 1);
//mNetFlags.mExtAddr = tmpaddr;
mNetFlags.mExtAddrOk = true;
mNetFlags.mExtAddrStableOk = isStable;
address_votes[tmpaddr].n++ ;
#ifdef NETMGR_DEBUG_STATEBOX
std::cerr << "p3NetMgrIMPL::netExtCheck() From DhtStunner: ";
std::cerr << sockaddr_storage_tostring(tmpaddr);
std::cerr << " Stable: " << (uint32_t) isstable;
std::cerr << std::endl;
#endif
}
else
std::cerr << "(SS) DHTStunner returned wrong own IP " << sockaddr_storage_iptostring(tmpaddr) << " (banned). Rejecting." << std::endl;
}
}
}
#endif
/* any other sources ??? */ /* any other sources ??? */
/* finalise address */ /* finalise address */

View File

@ -512,10 +512,10 @@ public:
RS_DEPRECATED_FOR(getChannelsInfo) RS_DEPRECATED_FOR(getChannelsInfo)
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsChannelGroup> &groups) = 0; virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsChannelGroup> &groups) = 0;
RS_DEPRECATED_FOR(getChannelsContent) RS_DEPRECATED_FOR(getChannelContent)
virtual bool getPostData(const uint32_t &token, std::vector<RsGxsChannelPost> &posts, std::vector<RsGxsComment> &cmts) = 0; virtual bool getPostData(const uint32_t &token, std::vector<RsGxsChannelPost> &posts, std::vector<RsGxsComment> &cmts) = 0;
RS_DEPRECATED_FOR(getChannelsContent) RS_DEPRECATED_FOR(getChannelContent)
virtual bool getPostData(const uint32_t &token, std::vector<RsGxsChannelPost> &posts) = 0; virtual bool getPostData(const uint32_t &token, std::vector<RsGxsChannelPost> &posts) = 0;
/** /**

View File

@ -3,7 +3,7 @@
* * * *
* libretroshare: retroshare core library * * libretroshare: retroshare core library *
* * * *
* Copyright 2008-2012 by Robert Fernie <retroshare@lunamutt.com> * * Copyright 2008-2020 by Robert Fernie <retroshare@lunamutt.com> *
* * * *
* This program is free software: you can redistribute it and/or modify * * This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as * * it under the terms of the GNU Lesser General Public License as *
@ -26,6 +26,7 @@
#include <string> #include <string>
#include <list> #include <list>
#include "rsgxsservice.h" #include "rsgxsservice.h"
#include "rsgxscommon.h"
/* The Main Interface Class - for information about your Peers */ /* The Main Interface Class - for information about your Peers */
class RsPhoto; class RsPhoto;
@ -37,21 +38,6 @@ extern RsPhoto *rsPhoto;
#define RSPHOTO_MODE_OWN 2 #define RSPHOTO_MODE_OWN 2
#define RSPHOTO_MODE_REMOTE 3 #define RSPHOTO_MODE_REMOTE 3
class RsPhotoThumbnail
{
public:
RsPhotoThumbnail()
:data(NULL), size(0), type("N/A") { return; }
bool deleteImage();
bool copyFrom(const RsPhotoThumbnail &nail);
// Holds Thumbnail image.
uint8_t *data;
uint32_t size;
std::string type;
};
/* If these flags are no set - the Photo inherits values from the Album /* If these flags are no set - the Photo inherits values from the Album
*/ */
@ -96,7 +82,7 @@ class RsPhotoPhoto
int mOrder; int mOrder;
RsPhotoThumbnail mThumbnail; RsGxsImage mThumbnail;
int mMode; int mMode;
@ -137,7 +123,7 @@ class RsPhotoAlbum
std::string mHashTags; std::string mHashTags;
RsPhotoThumbnail mThumbnail; RsGxsImage mThumbnail;
int mMode; int mMode;

View File

@ -3,7 +3,8 @@
* * * *
* libretroshare: retroshare core library * * libretroshare: retroshare core library *
* * * *
* Copyright 2008-2012 by Robert Fernie, Christopher Evi-Parker * * Copyright (C) 2008-2012 Robert Fernie, Christopher Evi-Parker *
* Copyright (C) 2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* * * *
* This program is free software: you can redistribute it and/or modify * * This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as * * it under the terms of the GNU Lesser General Public License as *
@ -19,8 +20,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * * along with this program. If not, see <https://www.gnu.org/licenses/>. *
* * * *
*******************************************************************************/ *******************************************************************************/
#ifndef RETROSHARE_GXS_RSPOSTED_GUI_INTERFACE_H #pragma once
#define RETROSHARE_GXS_RSPOSTED_GUI_INTERFACE_H
#include <inttypes.h> #include <inttypes.h>
#include <string> #include <string>
@ -32,126 +32,25 @@
#include "retroshare/rsgxscommon.h" #include "retroshare/rsgxscommon.h"
#include "serialiser/rsserializable.h" #include "serialiser/rsserializable.h"
/* The Main Interface Class - for information about your Posted */
class RsPosted; class RsPosted;
/**
* Pointer to global instance of RsGxsChannels service implementation
* @jsonapi{development}
*/
extern RsPosted* rsPosted; extern RsPosted* rsPosted;
class RsPostedPost; struct RsPostedGroup
class RsPostedGroup
{ {
public:
RsPostedGroup() { return; }
RsGroupMetaData mMeta; RsGroupMetaData mMeta;
std::string mDescription; std::string mDescription;
RsGxsImage mGroupImage; RsGxsImage mGroupImage;
}; };
struct RsPostedPost
//#define RSPOSTED_MSGTYPE_POST 0x0001
//#define RSPOSTED_MSGTYPE_VOTE 0x0002
//#define RSPOSTED_MSGTYPE_COMMENT 0x0004
#define RSPOSTED_PERIOD_YEAR 1
#define RSPOSTED_PERIOD_MONTH 2
#define RSPOSTED_PERIOD_WEEK 3
#define RSPOSTED_PERIOD_DAY 4
#define RSPOSTED_PERIOD_HOUR 5
#define RSPOSTED_VIEWMODE_LATEST 1
#define RSPOSTED_VIEWMODE_TOP 2
#define RSPOSTED_VIEWMODE_HOT 3
#define RSPOSTED_VIEWMODE_COMMENTS 4
std::ostream &operator<<(std::ostream &out, const RsPostedGroup &group);
std::ostream &operator<<(std::ostream &out, const RsPostedPost &post);
enum class RsPostedEventCode: uint8_t
{ {
UNKNOWN = 0x00, RsPostedPost(): mHaveVoted(false), mUpVotes(0), mDownVotes(0), mComments(0),
NEW_POSTED_GROUP = 0x01, mHotScore(0), mTopScore(0), mNewScore(0) {}
NEW_MESSAGE = 0x02,
SUBSCRIBE_STATUS_CHANGED = 0x03,
UPDATED_POSTED_GROUP = 0x04,
UPDATED_MESSAGE = 0x05,
READ_STATUS_CHANGED = 0x06,
};
struct RsGxsPostedEvent: RsEvent
{
RsGxsPostedEvent():
RsEvent(RsEventType::GXS_POSTED),
mPostedEventCode(RsPostedEventCode::UNKNOWN) {}
RsPostedEventCode mPostedEventCode;
RsGxsGroupId mPostedGroupId;
RsGxsMessageId mPostedMsgId;
///* @see RsEvent @see RsSerializable
void serial_process( RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override
{
RsEvent::serial_process(j, ctx);
RS_SERIAL_PROCESS(mPostedEventCode);
RS_SERIAL_PROCESS(mPostedGroupId);
RS_SERIAL_PROCESS(mPostedMsgId);
}
};
class RsPosted : public RsGxsIfaceHelper, public RsGxsCommentService
{
public:
enum RankType {TopRankType, HotRankType, NewRankType };
//static const uint32_t FLAG_MSGTYPE_POST;
//static const uint32_t FLAG_MSGTYPE_MASK;
explicit RsPosted(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {}
virtual ~RsPosted() {}
/* Specific Service Data */
virtual bool getGroupData(const uint32_t &token, std::vector<RsPostedGroup> &groups) = 0;
virtual bool getPostData(const uint32_t &token, std::vector<RsPostedPost> &posts, std::vector<RsGxsComment> &cmts) = 0;
virtual bool getPostData(const uint32_t &token, std::vector<RsPostedPost> &posts) = 0;
//Not currently used
//virtual bool getRelatedPosts(const uint32_t &token, std::vector<RsPostedPost> &posts) = 0;
/* From RsGxsCommentService */
//virtual bool getCommentData(const uint32_t &token, std::vector<RsGxsComment> &comments) = 0;
//virtual bool getRelatedComments(const uint32_t &token, std::vector<RsGxsComment> &comments) = 0;
//virtual bool createNewComment(uint32_t &token, RsGxsComment &comment) = 0;
//virtual bool createNewVote(uint32_t &token, RsGxsVote &vote) = 0;
//////////////////////////////////////////////////////////////////////////////
virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) = 0;
virtual bool createGroup(uint32_t &token, RsPostedGroup &group) = 0;
virtual bool createPost(uint32_t &token, RsPostedPost &post) = 0;
virtual bool updateGroup(uint32_t &token, RsPostedGroup &group) = 0;
virtual bool groupShareKeys(const RsGxsGroupId& group,const std::set<RsPeerId>& peers) = 0 ;
};
class RsPostedPost
{
public:
RsPostedPost()
{
//mMeta.mMsgFlags = RsPosted::FLAG_MSGTYPE_POST;
mUpVotes = 0;
mDownVotes = 0;
mComments = 0;
mHaveVoted = false;
mHotScore = 0;
mTopScore = 0;
mNewScore = 0;
}
bool calculateScores(rstime_t ref_time); bool calculateScores(rstime_t ref_time);
@ -192,4 +91,104 @@ class RsPostedPost
}; };
#endif // RETROSHARE_GXS_RSPOSTED_GUI_INTERFACE_H //#define RSPOSTED_MSGTYPE_POST 0x0001
//#define RSPOSTED_MSGTYPE_VOTE 0x0002
//#define RSPOSTED_MSGTYPE_COMMENT 0x0004
#define RSPOSTED_PERIOD_YEAR 1
#define RSPOSTED_PERIOD_MONTH 2
#define RSPOSTED_PERIOD_WEEK 3
#define RSPOSTED_PERIOD_DAY 4
#define RSPOSTED_PERIOD_HOUR 5
#define RSPOSTED_VIEWMODE_LATEST 1
#define RSPOSTED_VIEWMODE_TOP 2
#define RSPOSTED_VIEWMODE_HOT 3
#define RSPOSTED_VIEWMODE_COMMENTS 4
enum class RsPostedEventCode: uint8_t
{
UNKNOWN = 0x00,
NEW_POSTED_GROUP = 0x01,
NEW_MESSAGE = 0x02,
SUBSCRIBE_STATUS_CHANGED = 0x03,
UPDATED_POSTED_GROUP = 0x04,
UPDATED_MESSAGE = 0x05,
READ_STATUS_CHANGED = 0x06,
};
struct RsGxsPostedEvent: RsEvent
{
RsGxsPostedEvent():
RsEvent(RsEventType::GXS_POSTED),
mPostedEventCode(RsPostedEventCode::UNKNOWN) {}
RsPostedEventCode mPostedEventCode;
RsGxsGroupId mPostedGroupId;
RsGxsMessageId mPostedMsgId;
///* @see RsEvent @see RsSerializable
void serial_process( RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override
{
RsEvent::serial_process(j, ctx);
RS_SERIAL_PROCESS(mPostedEventCode);
RS_SERIAL_PROCESS(mPostedGroupId);
RS_SERIAL_PROCESS(mPostedMsgId);
}
~RsGxsPostedEvent() override;
};
class RsPosted : public RsGxsIfaceHelper, public RsGxsCommentService
{
public:
explicit RsPosted(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {}
virtual bool getBoardsInfo(
const std::list<RsGxsGroupId>& boardsIds,
std::vector<RsPostedGroup>& boardsInfo ) = 0;
virtual bool getBoardContent(
const RsGxsGroupId& boardId,
const std::set<RsGxsMessageId>& contentsIds,
std::vector<RsPostedPost>& posts,
std::vector<RsGxsComment>& comments ) = 0;
enum RS_DEPRECATED RankType {TopRankType, HotRankType, NewRankType };
RS_DEPRECATED_FOR(getBoardsInfo)
virtual bool getGroupData( const uint32_t& token,
std::vector<RsPostedGroup> &groups ) = 0;
RS_DEPRECATED_FOR(getBoardsContent)
virtual bool getPostData(
const uint32_t& token, std::vector<RsPostedPost>& posts,
std::vector<RsGxsComment>& cmts) = 0;
RS_DEPRECATED_FOR(getBoardsContent)
virtual bool getPostData(
const uint32_t& token, std::vector<RsPostedPost>& posts) = 0;
//Not currently used
//virtual bool getRelatedPosts(const uint32_t &token, std::vector<RsPostedPost> &posts) = 0;
/* From RsGxsCommentService */
//virtual bool getCommentData(const uint32_t &token, std::vector<RsGxsComment> &comments) = 0;
//virtual bool getRelatedComments(const uint32_t &token, std::vector<RsGxsComment> &comments) = 0;
//virtual bool createNewComment(uint32_t &token, RsGxsComment &comment) = 0;
//virtual bool createNewVote(uint32_t &token, RsGxsVote &vote) = 0;
//////////////////////////////////////////////////////////////////////////////
virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) = 0;
virtual bool createGroup(uint32_t &token, RsPostedGroup &group) = 0;
virtual bool createPost(uint32_t &token, RsPostedPost &post) = 0;
virtual bool updateGroup(uint32_t &token, RsPostedGroup &group) = 0;
virtual bool groupShareKeys(const RsGxsGroupId& group,const std::set<RsPeerId>& peers) = 0 ;
virtual ~RsPosted();
};

View File

@ -26,9 +26,6 @@
#include "serialiser/rstlvbinary.h" #include "serialiser/rstlvbinary.h"
#include "serialiser/rstypeserializer.h" #include "serialiser/rstypeserializer.h"
#define GXS_PHOTO_SERIAL_DEBUG
RsItem *RsGxsPhotoSerialiser::create_item(uint16_t service, uint8_t item_sub_id) const RsItem *RsGxsPhotoSerialiser::create_item(uint16_t service, uint8_t item_sub_id) const
{ {
if(service != RS_SERVICE_GXS_TYPE_PHOTO) if(service != RS_SERVICE_GXS_TYPE_PHOTO)
@ -37,8 +34,8 @@ RsItem *RsGxsPhotoSerialiser::create_item(uint16_t service, uint8_t item_sub_id)
switch(item_sub_id) switch(item_sub_id)
{ {
case RS_PKT_SUBTYPE_PHOTO_COMMENT_ITEM: return new RsGxsPhotoCommentItem() ; case RS_PKT_SUBTYPE_PHOTO_COMMENT_ITEM: return new RsGxsPhotoCommentItem() ;
case RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM: return new RsGxsPhotoAlbumItem() ; case RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM: return new RsGxsPhotoPhotoItem() ;
case RS_PKT_SUBTYPE_PHOTO_ITEM: return new RsGxsPhotoPhotoItem() ; case RS_PKT_SUBTYPE_PHOTO_ITEM: return new RsGxsPhotoAlbumItem() ;
default: default:
return NULL ; return NULL ;
} }
@ -55,10 +52,8 @@ void RsGxsPhotoAlbumItem::serial_process(RsGenericSerializer::SerializeJob j,RsG
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_NAME, album.mPhotographer, "mPhotographer"); RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_NAME, album.mPhotographer, "mPhotographer");
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DATE, album.mWhen, "mWhen"); RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DATE, album.mWhen, "mWhen");
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_LOCATION, album.mWhere, "mWhere"); RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_LOCATION, album.mWhere, "mWhere");
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_PIC_TYPE, album.mThumbnail.type,"mThumbnail.type");
RsTlvBinaryDataRef b(RS_SERVICE_GXS_TYPE_PHOTO, album.mThumbnail.data, album.mThumbnail.size); album.mThumbnail.serial_process(j, ctx);
RsTypeSerializer::serial_process<RsTlvItem>(j, ctx, b, "thumbnail binary data") ;
} }
void RsGxsPhotoPhotoItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) void RsGxsPhotoPhotoItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
{ {
@ -70,10 +65,8 @@ void RsGxsPhotoPhotoItem::serial_process(RsGenericSerializer::SerializeJob j,RsG
RsTypeSerializer::serial_process(j, ctx, TLV_TYPE_STR_PIC_AUTH, photo.mPhotographer, "mPhotographer"); RsTypeSerializer::serial_process(j, ctx, TLV_TYPE_STR_PIC_AUTH, photo.mPhotographer, "mPhotographer");
RsTypeSerializer::serial_process(j, ctx, TLV_TYPE_STR_DATE, photo.mWhen, "mWhen"); RsTypeSerializer::serial_process(j, ctx, TLV_TYPE_STR_DATE, photo.mWhen, "mWhen");
RsTypeSerializer::serial_process(j, ctx, TLV_TYPE_STR_LOCATION, photo.mWhere, "mWhere"); RsTypeSerializer::serial_process(j, ctx, TLV_TYPE_STR_LOCATION, photo.mWhere, "mWhere");
RsTypeSerializer::serial_process(j, ctx, TLV_TYPE_STR_PIC_TYPE, photo.mThumbnail.type, "mThumbnail.type");
RsTlvBinaryDataRef b(RS_SERVICE_GXS_TYPE_PHOTO, photo.mThumbnail.data, photo.mThumbnail.size); photo.mThumbnail.serial_process(j, ctx);
RsTypeSerializer::serial_process<RsTlvItem>(j, ctx, b, "mThumbnail") ;
} }
void RsGxsPhotoCommentItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) void RsGxsPhotoCommentItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
{ {
@ -92,7 +85,7 @@ void RsGxsPhotoAlbumItem::clear()
album.mPhotographer.clear(); album.mPhotographer.clear();
album.mWhen.clear(); album.mWhen.clear();
album.mWhere.clear(); album.mWhere.clear();
album.mThumbnail.deleteImage(); album.mThumbnail.clear();
} }
void RsGxsPhotoCommentItem::clear() void RsGxsPhotoCommentItem::clear()
@ -111,5 +104,5 @@ void RsGxsPhotoPhotoItem::clear()
photo.mPhotographer.clear(); photo.mPhotographer.clear();
photo.mWhen.clear(); photo.mWhen.clear();
photo.mWhere.clear(); photo.mWhere.clear();
photo.mThumbnail.deleteImage(); photo.mThumbnail.clear();
} }

View File

@ -30,46 +30,6 @@ const uint32_t RsPhoto::FLAG_MSG_TYPE_MASK = 0x000f;
const uint32_t RsPhoto::FLAG_MSG_TYPE_PHOTO_POST = 0x0001; const uint32_t RsPhoto::FLAG_MSG_TYPE_PHOTO_POST = 0x0001;
const uint32_t RsPhoto::FLAG_MSG_TYPE_PHOTO_COMMENT = 0x0002; const uint32_t RsPhoto::FLAG_MSG_TYPE_PHOTO_COMMENT = 0x0002;
bool RsPhotoThumbnail::copyFrom(const RsPhotoThumbnail &nail)
{
if (data)
{
deleteImage();
}
if ((!nail.data) || (nail.size == 0))
{
return false;
}
size = nail.size;
type = nail.type;
data = (uint8_t *) rs_malloc(size);
if(data == NULL)
return false ;
memcpy(data, nail.data, size);
return true;
}
bool RsPhotoThumbnail::deleteImage()
{
if (data)
{
free(data);
data = NULL;
size = 0;
type.clear();
}
return true;
}
RsPhotoPhoto::RsPhotoPhoto() RsPhotoPhoto::RsPhotoPhoto()
:mSetFlags(0), mOrder(0), mMode(0), mModFlags(0) :mSetFlags(0), mOrder(0), mMode(0), mModFlags(0)
{ {
@ -178,8 +138,9 @@ void p3PhotoService::groupsChanged(std::list<RsGxsGroupId>& grpIds)
RsGxsGroupChange* gc = mGroupChange.back(); RsGxsGroupChange* gc = mGroupChange.back();
std::list<RsGxsGroupId>& gList = gc->mGrpIdList; std::list<RsGxsGroupId>& gList = gc->mGrpIdList;
std::list<RsGxsGroupId>::iterator lit = gList.begin(); std::list<RsGxsGroupId>::iterator lit = gList.begin();
for(; lit != gList.end(); ++lit) for(; lit != gList.end(); ++lit) {
grpIds.push_back(*lit); grpIds.push_back(*lit);
}
mGroupChange.pop_back(); mGroupChange.pop_back();
delete gc; delete gc;
@ -210,7 +171,8 @@ RsTokenService* p3PhotoService::getTokenService() {
bool p3PhotoService::getGroupList(const uint32_t& token, bool p3PhotoService::getGroupList(const uint32_t& token,
std::list<RsGxsGroupId>& groupIds) std::list<RsGxsGroupId>& groupIds)
{ {
return RsGenExchange::getGroupList(token, groupIds); bool okay = RsGenExchange::getGroupList(token, groupIds);
return okay;
} }
@ -225,7 +187,8 @@ bool p3PhotoService::getMsgList(const uint32_t& token,
bool p3PhotoService::getGroupSummary(const uint32_t& token, bool p3PhotoService::getGroupSummary(const uint32_t& token,
std::list<RsGroupMetaData>& groupInfo) std::list<RsGroupMetaData>& groupInfo)
{ {
return RsGenExchange::getGroupMeta(token, groupInfo); bool okay = RsGenExchange::getGroupMeta(token, groupInfo);
return okay;
} }
@ -349,9 +312,7 @@ RsPhotoComment& RsPhotoComment::operator=(const RsGxsPhotoCommentItem& comment)
bool p3PhotoService::getPhotoRelatedComment(const uint32_t &token, PhotoRelatedCommentResult &comments) bool p3PhotoService::getPhotoRelatedComment(const uint32_t &token, PhotoRelatedCommentResult &comments)
{ {
return RsGenExchange::getMsgRelatedDataT<RsGxsPhotoCommentItem, RsPhotoComment>(token, comments); return RsGenExchange::getMsgRelatedDataT<RsGxsPhotoCommentItem, RsPhotoComment>(token, comments);
} }
bool p3PhotoService::submitAlbumDetails(uint32_t& token, RsPhotoAlbum& album) bool p3PhotoService::submitAlbumDetails(uint32_t& token, RsPhotoAlbum& album)
@ -397,7 +358,6 @@ bool p3PhotoService::submitPhoto(uint32_t& token, RsPhotoPhoto& photo)
RsGxsPhotoPhotoItem* photoItem = new RsGxsPhotoPhotoItem(); RsGxsPhotoPhotoItem* photoItem = new RsGxsPhotoPhotoItem();
photoItem->photo = photo; photoItem->photo = photo;
photoItem->meta = photo.mMeta; photoItem->meta = photo.mMeta;
photoItem->meta.mMsgFlags = FLAG_MSG_TYPE_PHOTO_POST;
RsGenExchange::publishMsg(token, photoItem); RsGenExchange::publishMsg(token, photoItem);
return true; return true;

View File

@ -30,7 +30,7 @@
* #define POSTED_DEBUG 1 * #define POSTED_DEBUG 1
****/ ****/
RsPosted *rsPosted = NULL; /*extern*/ RsPosted* rsPosted = nullptr;
/********************************************************************************/ /********************************************************************************/
/******************* Startup / Tick ******************************************/ /******************* Startup / Tick ******************************************/
@ -300,4 +300,35 @@ bool p3Posted::createPost(uint32_t &token, RsPostedPost &msg)
return true; return true;
} }
/********************************************************************************************/ bool p3Posted::getBoardsInfo(
const std::list<RsGxsGroupId>& boardsIds,
std::vector<RsPostedGroup>& channelsInfo )
{
uint32_t token;
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
if( !requestGroupInfo(token, opts, boardsIds)
|| waitToken(token) != RsTokenService::COMPLETE ) return false;
return getGroupData(token, channelsInfo) && !channelsInfo.empty();
}
bool p3Posted::getBoardContent( const RsGxsGroupId& channelId,
const std::set<RsGxsMessageId>& contentsIds,
std::vector<RsPostedPost>& posts,
std::vector<RsGxsComment>& comments )
{
uint32_t token;
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
GxsMsgReq msgIds;
msgIds[channelId] = contentsIds;
if( !requestMsgInfo(token, opts, msgIds) ||
waitToken(token) != RsTokenService::COMPLETE ) return false;
return getPostData(token, posts, comments);
}
RsPosted::~RsPosted() = default;
RsGxsPostedEvent::~RsGxsPostedEvent() = default;

View File

@ -44,9 +44,30 @@ class p3Posted: public p3PostBase, public RsPosted
p3Posted(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs* gixs); p3Posted(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs* gixs);
virtual RsServiceInfo getServiceInfo(); virtual RsServiceInfo getServiceInfo();
protected:
virtual void notifyChanges(std::vector<RsGxsNotify*>& changes)
{
return p3PostBase::notifyChanges(changes);
}
public: public:
// Posted Specific DataTypes. virtual void receiveHelperChanges(std::vector<RsGxsNotify*>& changes)
{
return RsGxsIfaceHelper::receiveChanges(changes);
}
bool getBoardsInfo(
const std::list<RsGxsGroupId>& boardsIds,
std::vector<RsPostedGroup>& channelsInfo ) override;
bool getBoardContent(
const RsGxsGroupId& boardId,
const std::set<RsGxsMessageId>& contentsIds,
std::vector<RsPostedPost>& posts,
std::vector<RsGxsComment>& comments ) override;
virtual bool getGroupData(const uint32_t &token, std::vector<RsPostedGroup> &groups); virtual bool getGroupData(const uint32_t &token, std::vector<RsPostedGroup> &groups);
virtual bool getPostData(const uint32_t &token, std::vector<RsPostedPost> &posts, std::vector<RsGxsComment> &cmts); virtual bool getPostData(const uint32_t &token, std::vector<RsPostedPost> &posts, std::vector<RsGxsComment> &cmts);
virtual bool getPostData(const uint32_t &token, std::vector<RsPostedPost> &posts) { std::vector<RsGxsComment> cmts; return getPostData( token, posts, cmts);} virtual bool getPostData(const uint32_t &token, std::vector<RsPostedPost> &posts) { std::vector<RsGxsComment> cmts; return getPostData( token, posts, cmts);}

View File

@ -164,12 +164,12 @@ int UdpStunner::grabExclusiveMode(std::string holder) /* returns seconds since
commsage = 1; commsage = 1;
} }
#ifdef DEBUG_UDP_STUNNER_FILTER #ifdef DEBUG_UDP_STUNNER_FILTER
#endif
std::cerr << "UdpStunner::grabExclusiveMode() SUCCESS. last comms: " << commsage; std::cerr << "UdpStunner::grabExclusiveMode() SUCCESS. last comms: " << commsage;
std::cerr << " ago"; std::cerr << " ago";
std::cerr << std::endl; std::cerr << std::endl;
std::cerr << "UdpStunner::grabExclusiveMode() Exclusive held by: " << mExclusiveHolder; std::cerr << "UdpStunner::grabExclusiveMode() Exclusive held by: " << mExclusiveHolder;
std::cerr << std::endl; std::cerr << std::endl;
#endif
return commsage; return commsage;
} }
@ -181,13 +181,12 @@ int UdpStunner::releaseExclusiveMode(std::string holder, bool forceStun)
if (!mExclusiveMode) if (!mExclusiveMode)
{ {
#ifdef DEBUG_UDP_STUNNER_FILTER #ifdef DEBUG_UDP_STUNNER_FILTER
#endif
std::cerr << "UdpStunner::cancelExclusiveMode() ERROR, not in exclusive Mode"; std::cerr << "UdpStunner::cancelExclusiveMode() ERROR, not in exclusive Mode";
std::cerr << std::endl; std::cerr << std::endl;
#endif
return 0; return 0;
} }
rstime_t now = time(NULL);
mExclusiveMode = false; mExclusiveMode = false;
if (forceStun) if (forceStun)
{ {
@ -217,10 +216,11 @@ int UdpStunner::releaseExclusiveMode(std::string holder, bool forceStun)
} }
#ifdef DEBUG_UDP_STUNNER_FILTER #ifdef DEBUG_UDP_STUNNER_FILTER
#endif rstime_t now = time(nullptr);
std::cerr << "UdpStunner::cancelExclusiveMode() Canceled. Was in ExclusiveMode for: " << now - mExclusiveModeTS; std::cerr << "UdpStunner::cancelExclusiveMode() Canceled. Was in ExclusiveMode for: " << now - mExclusiveModeTS;
std::cerr << " secs"; std::cerr << " secs";
std::cerr << std::endl; std::cerr << std::endl;
#endif
return 1; return 1;
} }
@ -326,7 +326,7 @@ bool UdpStunner::locked_handleStunPkt(void *data, int size, struct sockaddr_in &
#endif #endif
/* generate a response */ /* generate a response */
int len; int len;
void *pkt = UdpStun_generate_stun_reply(&from, &len); void *pkt = UdpStun_generate_stun_reply(&from, &len, data);
if (!pkt) if (!pkt)
return false; return false;
@ -485,7 +485,7 @@ bool UdpStun_response(void *stun_pkt, int size, struct sockaddr_in &addr)
return false; return false;
} }
if (htons(((uint16_t *) stun_pkt)[0]) != 0x0101) if (htons(((uint16_t *) stun_pkt)[0]) != UdpStunner::STUN_BINDING_RESPONSE)
{ {
/* not a response */ /* not a response */
return false; return false;
@ -517,33 +517,38 @@ bool UdpStun_generate_stun_pkt(void *stun_pkt, int *len)
} }
/* just the header */ /* just the header */
((uint16_t *) stun_pkt)[0] = (uint16_t) htons(0x0001); ((uint16_t *) stun_pkt)[0] = (uint16_t) htons(UdpStunner::STUN_BINDING_REQUEST);
((uint16_t *) stun_pkt)[1] = (uint16_t) htons(20); /* only header */ ((uint16_t *) stun_pkt)[1] = (uint16_t) htons(20); /* only header */
/* transaction id - should be random */ /* RFC 3489
((uint32_t *) stun_pkt)[1] = (uint32_t) htonl(0x0020); * The transaction ID is used to correlate requests and responses.
((uint32_t *) stun_pkt)[2] = (uint32_t) htonl(0x0121); *
((uint32_t *) stun_pkt)[3] = (uint32_t) htonl(0x0111); * RFC 5389 introduces a mmgic cokie at the location where preciously the transaction ID was located:
((uint32_t *) stun_pkt)[4] = (uint32_t) htonl(0x1010); * In RFC 3489, this field was part of
* the transaction ID; placing the magic cookie in this location allows
* a server to detect if the client will understand certain attributes
* that were added in this revised specification.
*/
RsRandom::random_bytes(&((uint8_t *) stun_pkt)[4], 4 * sizeof (uint32_t));
*len = 20; *len = 20;
return true; return true;
} }
void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len) void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len, const void *transId)
{ {
/* just the header */ /* just the header */
void *stun_pkt = rs_malloc(28); void *stun_pkt = rs_malloc(28);
if(!stun_pkt) if(!stun_pkt)
return NULL ; return nullptr ;
((uint16_t *) stun_pkt)[0] = (uint16_t) htons(0x0101); ((uint16_t *) stun_pkt)[0] = (uint16_t) htons(UdpStunner::STUN_BINDING_RESPONSE);
((uint16_t *) stun_pkt)[1] = (uint16_t) htons(28); /* only header + 8 byte addr */ ((uint16_t *) stun_pkt)[1] = (uint16_t) htons(28); /* only header + 8 byte addr */
/* transaction id - should be random */ /* RFC 3489
((uint32_t *) stun_pkt)[1] = (uint32_t) htonl(0x0f20); * The Binding Response MUST contain the same transaction ID contained in the Binding Request.
((uint32_t *) stun_pkt)[2] = (uint32_t) htonl(0x0f21); */
((uint32_t *) stun_pkt)[3] = (uint32_t) htonl(0x0f11); memcpy(&((uint32_t *) stun_pkt)[1], &((uint32_t *) transId)[1], 4 * sizeof (uint32_t));
((uint32_t *) stun_pkt)[4] = (uint32_t) htonl(0x1010);
/* now add address /* now add address
* 0 1 2 3 * 0 1 2 3
* <INET> <port> * <INET> <port>
@ -586,20 +591,20 @@ bool UdpStun_isStunPacket(void *data, int size)
return false; return false;
} }
if ((size == 20) && (0x0001 == ntohs(((uint16_t *) data)[0]))) if ((size == 20) && (UdpStunner::STUN_BINDING_REQUEST == ntohs(((uint16_t *) data)[0])))
{ {
#ifdef DEBUG_UDP_STUNNER_FILTER #ifdef DEBUG_UDP_STUNNER_FILTER
std::cerr << "UdpStunner::isStunPacket() (size=20 & data[0]=0x0001) -> true"; std::cerr << "UdpStunner::isStunPacket() (size=20 & data[0]=STUN_BINDING_REQUEST) -> true";
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
/* request */ /* request */
return true; return true;
} }
if ((size == 28) && (0x0101 == ntohs(((uint16_t *) data)[0]))) if ((size == 28) && (UdpStunner::STUN_BINDING_RESPONSE == ntohs(((uint16_t *) data)[0])))
{ {
#ifdef DEBUG_UDP_STUNNER_FILTER #ifdef DEBUG_UDP_STUNNER_FILTER
std::cerr << "UdpStunner::isStunPacket() (size=28 & data[0]=0x0101) -> true"; std::cerr << "UdpStunner::isStunPacket() (size=28 & data[0]=STUN_BINDING_RESPONSE) -> true";
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
/* response */ /* response */
@ -947,15 +952,15 @@ bool UdpStunner::locked_recvdStun(const struct sockaddr_in &remote, const str
if (remote.sin_addr.s_addr == extaddr.sin_addr.s_addr) if (remote.sin_addr.s_addr == extaddr.sin_addr.s_addr)
{ {
#ifdef DEBUG_UDP_STUNNER #ifdef DEBUG_UDP_STUNNER
#endif
std::cerr << "UdpStunner::locked_recvdStun() WARNING, BAD PEER: "; std::cerr << "UdpStunner::locked_recvdStun() WARNING, BAD PEER: ";
std::cerr << "Stun Peer Returned its own address: " << rs_inet_ntoa(remote.sin_addr); std::cerr << "Stun Peer Returned its own address: " << rs_inet_ntoa(remote.sin_addr);
std::cerr << std::endl; std::cerr << std::endl;
#endif
return false; return false;
} }
#endif #endif
bool found = true; bool found = false;
std::list<TouStunPeer>::iterator it; std::list<TouStunPeer>::iterator it;
for(it = mStunList.begin(); it != mStunList.end(); ++it) for(it = mStunList.begin(); it != mStunList.end(); ++it)
{ {

View File

@ -30,10 +30,10 @@
#include "util/rsthreads.h" #include "util/rsthreads.h"
#include <string> #include <string>
/* UdpStun. /**
* @brief The TouStunPeer class
* Stuns peers to determine external addresses. * Stuns peers to determine external addresses.
*/ */
class TouStunPeer class TouStunPeer
{ {
public: public:
@ -53,10 +53,17 @@ class TouStunPeer
return; return;
} }
/// id for identification
std::string id; std::string id;
struct sockaddr_in remote, eaddr; /// Remote address of the peer.
struct sockaddr_in remote;
/// Our external IP address as reported by the peer.
struct sockaddr_in eaddr;
/// true when a response was received in the past
bool response; bool response;
/// used to rate limit STUN requests
rstime_t lastsend; rstime_t lastsend;
/// fail counter for dead/bad peer detection (0 = good)
uint32_t failCount; uint32_t failCount;
}; };
@ -65,6 +72,13 @@ class TouStunPeer
* #define UDPSTUN_ALLOW_LOCALNET 1 * #define UDPSTUN_ALLOW_LOCALNET 1
*/ */
/**
* @brief The UdpStunner class
* The UDP stunner implements the STUN protocol to determin the NAT type (behind that RS is usually running).
* It maintains a list of DHT peers that are regulary contacted.
*
* The actual NAT type determination logic is located in void pqiNetStateBox::determineNetworkState()
*/
class UdpStunner: public UdpSubReceiver class UdpStunner: public UdpSubReceiver
{ {
public: public:
@ -102,6 +116,12 @@ virtual int status(std::ostream &out);
/* monitoring / updates */ /* monitoring / updates */
int tick(); int tick();
/*
* based on RFC 3489
*/
static constexpr uint16_t STUN_BINDING_REQUEST = 0x0001;
static constexpr uint16_t STUN_BINDING_RESPONSE = 0x0101;
private: private:
bool checkStunDesired(); bool checkStunDesired();
@ -143,13 +163,19 @@ bool locked_checkExternalAddress();
#endif #endif
/// The UDP stunner will only (actively) contact it's peers when mPassiveStunMode is false. (has priority over mForceRestun
bool mPassiveStunMode; bool mPassiveStunMode;
/// Time between STUNs
uint32_t mTargetStunPeriod; uint32_t mTargetStunPeriod;
/// Rate that determines how often STUN attempts are successfull
double mSuccessRate; double mSuccessRate;
/// Some variables used for tracking who and when exclusive mode is enabled
bool mExclusiveMode; /* when this is switched on, the stunner stays silent (and extAddr is maintained) */ bool mExclusiveMode; /* when this is switched on, the stunner stays silent (and extAddr is maintained) */
rstime_t mExclusiveModeTS; rstime_t mExclusiveModeTS;
std::string mExclusiveHolder; std::string mExclusiveHolder;
/// force a STUN immediately
bool mForceRestun; bool mForceRestun;
}; };
@ -158,7 +184,14 @@ bool locked_checkExternalAddress();
bool UdpStun_isStunPacket(void *data, int size); bool UdpStun_isStunPacket(void *data, int size);
bool UdpStun_response(void *stun_pkt, int size, struct sockaddr_in &addr); bool UdpStun_response(void *stun_pkt, int size, struct sockaddr_in &addr);
void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len); /**
* @brief UdpStun_generate_stun_reply Generates a STUN reply package.
* @param stun_addr The address to set in the response field.
* @param len Lenght of the generated package (always 28).
* @param transId The transaction ID of the request package.
* @return Pointer to the generated reply package.
*/
void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len, const void* transId);
bool UdpStun_generate_stun_pkt(void *stun_pkt, int *len); bool UdpStun_generate_stun_pkt(void *stun_pkt, int *len);
#endif #endif

View File

@ -128,7 +128,7 @@ void AlbumCreateDialog::publishPhotos()
} }
bool AlbumCreateDialog::getAlbumThumbnail(RsPhotoThumbnail &nail) bool AlbumCreateDialog::getAlbumThumbnail(RsGxsImage &image)
{ {
const QPixmap *tmppix = &mThumbNail; const QPixmap *tmppix = &mThumbNail;
@ -142,17 +142,11 @@ bool AlbumCreateDialog::getAlbumThumbnail(RsPhotoThumbnail &nail)
buffer.open(QIODevice::WriteOnly); buffer.open(QIODevice::WriteOnly);
tmppix->save(&buffer, "PNG"); // writes image into ba in PNG format tmppix->save(&buffer, "PNG"); // writes image into ba in PNG format
RsPhotoThumbnail tmpnail; image.copy((uint8_t *) ba.data(), ba.size());
tmpnail.data = (uint8_t *) ba.data();
tmpnail.size = ba.size();
nail.copyFrom(tmpnail);
return true; return true;
} }
nail.data = NULL; image.clear();
nail.size = 0;
return false; return false;
} }

View File

@ -55,7 +55,7 @@ private slots:
private: private:
bool getAlbumThumbnail(RsPhotoThumbnail &nail); bool getAlbumThumbnail(RsGxsImage &image);
private: private:
Ui::AlbumCreateDialog *ui; Ui::AlbumCreateDialog *ui;

View File

@ -60,11 +60,11 @@ void AlbumDialog::setUp()
ui->textEdit_description->setText(QString::fromStdString(mAlbum.mDescription)); ui->textEdit_description->setText(QString::fromStdString(mAlbum.mDescription));
QPixmap qtn;
GxsIdDetails::loadPixmapFromData(mAlbum.mThumbnail.data, mAlbum.mThumbnail.size,qtn, GxsIdDetails::ORIGINAL);
if(mAlbum.mThumbnail.size != 0) if(mAlbum.mThumbnail.mSize != 0)
{ {
QPixmap qtn;
GxsIdDetails::loadPixmapFromData(mAlbum.mThumbnail.mData, mAlbum.mThumbnail.mSize,qtn, GxsIdDetails::ORIGINAL);
ui->label_thumbNail->setPixmap(qtn); ui->label_thumbNail->setPixmap(qtn);
} }
else else

View File

@ -0,0 +1,41 @@
/*******************************************************************************
* retroshare-gui/src/gui/PhotoShare/AlbumExtra.cpp *
* *
* Copyright (C) 2018 by Robert Fernie <retroshare.project@gmail.com> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#include "AlbumExtra.h"
#include "ui_AlbumExtra.h"
AlbumExtra::AlbumExtra(QWidget *parent) :
QWidget(NULL),
ui(new Ui::AlbumExtra)
{
ui->setupUi(this);
setUp();
}
AlbumExtra::~AlbumExtra()
{
delete ui;
}
void AlbumExtra::setUp()
{
}

View File

@ -0,0 +1,44 @@
/*******************************************************************************
* retroshare-gui/src/gui/PhotoShare/AlbumExtra.h *
* *
* Copyright (C) 2020 by Robert Fernie <retroshare.project@gmail.com> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#ifndef ALBUMEXTRA_H
#define ALBUMEXTRA_H
#include <QWidget>
namespace Ui {
class AlbumExtra;
}
class AlbumExtra : public QWidget
{
Q_OBJECT
public:
explicit AlbumExtra(QWidget *parent = 0);
virtual ~AlbumExtra();
private:
void setUp();
private:
Ui::AlbumExtra *ui;
};
#endif // ALBUMEXTRA_H

View File

@ -0,0 +1,162 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AlbumExtra</class>
<widget class="QWidget" name="AlbumExtra">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>513</width>
<height>198</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_19">
<property name="text">
<string>Category:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBox_Category_2">
<item>
<property name="text">
<string>Animals</string>
</property>
</item>
<item>
<property name="text">
<string>Family</string>
</property>
</item>
<item>
<property name="text">
<string>Friends</string>
</property>
</item>
<item>
<property name="text">
<string>Flowers</string>
</property>
</item>
<item>
<property name="text">
<string>Holiday</string>
</property>
</item>
<item>
<property name="text">
<string>Landscapes</string>
</property>
</item>
<item>
<property name="text">
<string>Pets</string>
</property>
</item>
<item>
<property name="text">
<string>Portraits</string>
</property>
</item>
<item>
<property name="text">
<string>Travel</string>
</property>
</item>
<item>
<property name="text">
<string>Work</string>
</property>
</item>
<item>
<property name="text">
<string>Random</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Quality:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboBox_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Resize Images (&lt; 1Mb)</string>
</property>
</item>
<item>
<property name="text">
<string>Resize Images (&lt; 10Mb)</string>
</property>
</item>
<item>
<property name="text">
<string>Send Original Images</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="captionLabel">
<property name="text">
<string>Caption:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="lineEdit_Caption_2"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Where:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="lineEdit_Where"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Photographer:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="lineEdit_Photographer"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,186 @@
/*******************************************************************************
* retroshare-gui/src/gui/PhotoShare/AlbumGroupDialog.cpp *
* *
* Copyright (C) 2020 by Robert Fernie <retroshare.project@gmail.com> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#include <QBuffer>
#include "AlbumGroupDialog.h"
#include "AlbumExtra.h"
#include "gui/gxs/GxsIdDetails.h"
#include <iostream>
const uint32_t AlbumCreateEnabledFlags = (
GXS_GROUP_FLAGS_NAME |
GXS_GROUP_FLAGS_ICON |
GXS_GROUP_FLAGS_DESCRIPTION |
GXS_GROUP_FLAGS_DISTRIBUTION |
// GXS_GROUP_FLAGS_PUBLISHSIGN |
// GXS_GROUP_FLAGS_SHAREKEYS | // disabled because the UI doesn't handle it yet.
// GXS_GROUP_FLAGS_PERSONALSIGN |
// GXS_GROUP_FLAGS_COMMENTS |
GXS_GROUP_FLAGS_EXTRA |
0);
uint32_t AlbumCreateDefaultsFlags = ( GXS_GROUP_DEFAULTS_DISTRIB_PUBLIC |
//GXS_GROUP_DEFAULTS_DISTRIB_GROUP |
//GXS_GROUP_DEFAULTS_DISTRIB_LOCAL |
GXS_GROUP_DEFAULTS_PUBLISH_OPEN |
//GXS_GROUP_DEFAULTS_PUBLISH_THREADS |
//GXS_GROUP_DEFAULTS_PUBLISH_REQUIRED |
//GXS_GROUP_DEFAULTS_PUBLISH_ENCRYPTED |
//GXS_GROUP_DEFAULTS_PERSONAL_GPG |
GXS_GROUP_DEFAULTS_PERSONAL_REQUIRED |
//GXS_GROUP_DEFAULTS_PERSONAL_IFNOPUB |
//GXS_GROUP_DEFAULTS_COMMENTS_YES |
GXS_GROUP_DEFAULTS_COMMENTS_NO |
0);
uint32_t AlbumEditEnabledFlags = AlbumCreateEnabledFlags;
uint32_t AlbumEditDefaultsFlags = AlbumCreateDefaultsFlags;
AlbumGroupDialog::AlbumGroupDialog(TokenQueue *tokenQueue, QWidget *parent)
: GxsGroupDialog(tokenQueue, AlbumCreateEnabledFlags, AlbumCreateDefaultsFlags, parent)
{
}
AlbumGroupDialog::AlbumGroupDialog(TokenQueue *tokenExternalQueue, RsTokenService *tokenService, Mode mode, RsGxsGroupId groupId, QWidget *parent)
: GxsGroupDialog(tokenExternalQueue, tokenService, mode, groupId, AlbumEditEnabledFlags, AlbumEditDefaultsFlags, parent)
{
}
void AlbumGroupDialog::initUi()
{
switch (mode())
{
case MODE_CREATE:
setUiText(UITYPE_SERVICE_HEADER, tr("Create New Album"));
setUiText(UITYPE_BUTTONBOX_OK, tr("Create"));
break;
case MODE_SHOW:
setUiText(UITYPE_SERVICE_HEADER, tr("Album"));
break;
case MODE_EDIT:
setUiText(UITYPE_SERVICE_HEADER, tr("Edit ALbum"));
setUiText(UITYPE_BUTTONBOX_OK, tr("Update Album"));
break;
}
setUiText(UITYPE_ADD_ADMINS_CHECKBOX, tr("Add Album Admins"));
setUiText(UITYPE_CONTACTS_DOCK, tr("Select Album Admins"));
// Inject Extra Widgets.
injectExtraWidget(new AlbumExtra(this));
}
QPixmap AlbumGroupDialog::serviceImage()
{
return QPixmap(":/images/album_create_64.png");
}
void AlbumGroupDialog::prepareAlbumGroup(RsPhotoAlbum &group, const RsGroupMetaData &meta)
{
group.mMeta = meta;
group.mDescription = getDescription().toUtf8().constData();
QPixmap pixmap = getLogo();
if (!pixmap.isNull()) {
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
pixmap.save(&buffer, "PNG"); // writes image into ba in PNG format
group.mThumbnail.copy((uint8_t *) ba.data(), ba.size());
} else {
group.mThumbnail.clear();
}
// Additional Fields that we need to fill in.
group.mCaption = "Caption goes here";
group.mPhotographer = "photographer";
group.mWhere = "Where?";
}
bool AlbumGroupDialog::service_CreateGroup(uint32_t &token, const RsGroupMetaData &meta)
{
// Specific Function.
RsPhotoAlbum grp;
prepareAlbumGroup(grp, meta);
rsPhoto->submitAlbumDetails(token, grp);
return true;
}
bool AlbumGroupDialog::service_EditGroup(uint32_t &token, RsGroupMetaData &editedMeta)
{
RsPhotoAlbum grp;
prepareAlbumGroup(grp, editedMeta);
std::cerr << "AlbumGroupDialog::service_EditGroup() submitting changes";
std::cerr << std::endl;
// TODO: no interface here, yet.
// rsPhoto->updateGroup(token, grp);
return true;
}
bool AlbumGroupDialog::service_loadGroup(uint32_t token, Mode /*mode*/, RsGroupMetaData& groupMetaData, QString &description)
{
std::cerr << "AlbumGroupDialog::service_loadGroup(" << token << ")";
std::cerr << std::endl;
std::vector<RsPhotoAlbum> groups;
if (!rsPhoto->getAlbum(token, groups))
{
std::cerr << "AlbumGroupDialog::service_loadGroup() Error getting GroupData";
std::cerr << std::endl;
return false;
}
if (groups.size() != 1)
{
std::cerr << "AlbumGroupDialog::service_loadGroup() Error Group.size() != 1";
std::cerr << std::endl;
return false;
}
std::cerr << "AlbumGroupDialog::service_loadGroup() Unfinished Loading";
std::cerr << std::endl;
const RsPhotoAlbum &group = groups[0];
groupMetaData = group.mMeta;
description = QString::fromUtf8(group.mDescription.c_str());
if (group.mThumbnail.mData) {
QPixmap pixmap;
if (GxsIdDetails::loadPixmapFromData(group.mThumbnail.mData, group.mThumbnail.mSize, pixmap,GxsIdDetails::ORIGINAL)) {
setLogo(pixmap);
}
} else {
setLogo(QPixmap(":/images/album_create_64.png"));
}
// NEED TO Load additional data....
return true;
}

View File

@ -0,0 +1,47 @@
/*******************************************************************************
* retroshare-gui/src/gui/Posted/PostedGroupDialog.h *
* *
* Copyright (C) 2020 by Robert Fernie <retroshare.project@gmail.com> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#ifndef _ALBUM_GROUP_DIALOG_H
#define _ALBUM_GROUP_DIALOG_H
#include "gui/gxs/GxsGroupDialog.h"
#include <retroshare/rsphoto.h>
class AlbumGroupDialog : public GxsGroupDialog
{
Q_OBJECT
public:
AlbumGroupDialog(TokenQueue *tokenQueue, QWidget *parent);
AlbumGroupDialog(TokenQueue *tokenExternalQueue, RsTokenService *tokenService, Mode mode, RsGxsGroupId groupId, QWidget *parent);
protected:
virtual void initUi();
virtual QPixmap serviceImage();
virtual bool service_CreateGroup(uint32_t &token, const RsGroupMetaData &meta);
virtual bool service_loadGroup(uint32_t token, Mode mode, RsGroupMetaData& groupMetaData, QString &description);
virtual bool service_EditGroup(uint32_t &token, RsGroupMetaData &editedMeta);
private:
void prepareAlbumGroup(RsPhotoAlbum &group, const RsGroupMetaData &meta);
};
#endif

View File

@ -41,11 +41,11 @@ void AlbumItem::setUp()
{ {
ui->label_AlbumTitle->setText(QString::fromStdString(mAlbum.mMeta.mGroupName)); ui->label_AlbumTitle->setText(QString::fromStdString(mAlbum.mMeta.mGroupName));
ui->label_Photographer->setText(QString::fromStdString(mAlbum.mPhotographer)); ui->label_Photographer->setText(QString::fromStdString(mAlbum.mPhotographer));
QPixmap qtn;
qtn.loadFromData(mAlbum.mThumbnail.data, mAlbum.mThumbnail.size, mAlbum.mThumbnail.type.c_str());
if(mAlbum.mThumbnail.size != 0) if(mAlbum.mThumbnail.mSize != 0)
{ {
QPixmap qtn;
qtn.loadFromData(mAlbum.mThumbnail.mData, mAlbum.mThumbnail.mSize, "PNG");
ui->label_Thumbnail->setPixmap(qtn); ui->label_Thumbnail->setPixmap(qtn);
} }
else else

View File

@ -53,7 +53,7 @@ PhotoDialog::~PhotoDialog()
void PhotoDialog::setUp() void PhotoDialog::setUp()
{ {
QPixmap qtn; QPixmap qtn;
qtn.loadFromData(mPhotoDetails.mThumbnail.data, mPhotoDetails.mThumbnail.size, mPhotoDetails.mThumbnail.type.c_str()); qtn.loadFromData(mPhotoDetails.mThumbnail.mData, mPhotoDetails.mThumbnail.mSize, "PNG");
ui->label_Photo->setPixmap(qtn); ui->label_Photo->setPixmap(qtn);
ui->lineEdit_Title->setText(QString::fromStdString(mPhotoDetails.mMeta.mMsgName)); ui->lineEdit_Title->setText(QString::fromStdString(mPhotoDetails.mMeta.mMsgName));

View File

@ -60,7 +60,7 @@ PhotoItem::PhotoItem(PhotoShareItemHolder *holder, const QString& path, QWidget
ui->label_Thumbnail->setPixmap(mThumbNail.scaled(120, 120, Qt::KeepAspectRatio, Qt::SmoothTransformation)); ui->label_Thumbnail->setPixmap(mThumbNail.scaled(120, 120, Qt::KeepAspectRatio, Qt::SmoothTransformation));
setSelected(false); setSelected(false);
getPhotoThumbnail(mPhotoDetails.mThumbnail); getThumbnail(mPhotoDetails.mThumbnail);
connect(ui->lineEdit_Title, SIGNAL(editingFinished()), this, SLOT(setTitle())); connect(ui->lineEdit_Title, SIGNAL(editingFinished()), this, SLOT(setTitle()));
connect(ui->lineEdit_PhotoGrapher, SIGNAL(editingFinished()), this, SLOT(setPhotoGrapher())); connect(ui->lineEdit_PhotoGrapher, SIGNAL(editingFinished()), this, SLOT(setPhotoGrapher()));
@ -83,7 +83,7 @@ void PhotoItem::setSelected(bool selected)
update(); update();
} }
bool PhotoItem::getPhotoThumbnail(RsPhotoThumbnail &nail) bool PhotoItem::getThumbnail(RsGxsImage &image)
{ {
const QPixmap *tmppix = &mThumbNail; const QPixmap *tmppix = &mThumbNail;
@ -96,18 +96,11 @@ bool PhotoItem::getPhotoThumbnail(RsPhotoThumbnail &nail)
buffer.open(QIODevice::WriteOnly); buffer.open(QIODevice::WriteOnly);
tmppix->save(&buffer, "PNG"); // writes image into ba in PNG format tmppix->save(&buffer, "PNG"); // writes image into ba in PNG format
image.copy((uint8_t *) ba.data(), ba.size());
RsPhotoThumbnail tmpnail;
tmpnail.data = (uint8_t *) ba.data();
tmpnail.size = ba.size();
nail.copyFrom(tmpnail);
return true; return true;
} }
nail.data = NULL; image.clear();
nail.size = 0;
return false; return false;
} }
@ -166,12 +159,12 @@ void PhotoItem::setUp()
updateImage(mPhotoDetails.mThumbnail); updateImage(mPhotoDetails.mThumbnail);
} }
void PhotoItem::updateImage(const RsPhotoThumbnail &thumbnail) void PhotoItem::updateImage(const RsGxsImage &image)
{ {
if (thumbnail.data != NULL) if (image.mData != NULL)
{ {
QPixmap qtn; QPixmap qtn;
qtn.loadFromData(thumbnail.data, thumbnail.size, thumbnail.type.c_str()); qtn.loadFromData(image.mData, image.mSize, "PNG");
ui->label_Thumbnail->setPixmap(qtn.scaled(120, 120, Qt::KeepAspectRatio, Qt::SmoothTransformation)); ui->label_Thumbnail->setPixmap(qtn.scaled(120, 120, Qt::KeepAspectRatio, Qt::SmoothTransformation));
mThumbNail = qtn; mThumbNail = qtn;
} }

View File

@ -42,13 +42,13 @@ public:
void setSelected(bool selected); void setSelected(bool selected);
bool isSelected(){ return mSelected; } bool isSelected(){ return mSelected; }
const RsPhotoPhoto& getPhotoDetails(); const RsPhotoPhoto& getPhotoDetails();
bool getPhotoThumbnail(RsPhotoThumbnail &nail); bool getThumbnail(RsGxsImage &image);
protected: protected:
void mousePressEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event);
private: private:
void updateImage(const RsPhotoThumbnail &thumbnail); void updateImage(const RsGxsImage &image);
void setUp(); void setUp();
private slots: private slots:

View File

@ -31,7 +31,7 @@
#include <QTimer> #include <QTimer>
#include <QMessageBox> #include <QMessageBox>
#include "AlbumCreateDialog.h" #include "AlbumGroupDialog.h"
#include "AlbumItem.h" #include "AlbumItem.h"
#include "PhotoItem.h" #include "PhotoItem.h"
@ -215,7 +215,7 @@ void PhotoShare::OpenSlideShow()
void PhotoShare::createAlbum() void PhotoShare::createAlbum()
{ {
AlbumCreateDialog albumCreate(mPhotoQueue, rsPhoto, this); AlbumGroupDialog albumCreate(mPhotoQueue, this);
albumCreate.exec(); albumCreate.exec();
} }

View File

@ -28,7 +28,6 @@
#include "retroshare/rsphoto.h" #include "retroshare/rsphoto.h"
#include "retroshare-gui/mainpage.h" #include "retroshare-gui/mainpage.h"
#include "AlbumCreateDialog.h"
#include "AlbumDialog.h" #include "AlbumDialog.h"
#include "PhotoDialog.h" #include "PhotoDialog.h"
@ -39,7 +38,7 @@
#include "util/TokenQueue.h" #include "util/TokenQueue.h"
#include "PhotoShareItemHolder.h" #include "PhotoShareItemHolder.h"
#define IMAGE_PHOTO ":/images/lphoto.png" #define IMAGE_PHOTO ":/icons/png/photo.png"
namespace Ui { namespace Ui {
class PhotoShare; class PhotoShare;

View File

@ -20,6 +20,7 @@
#include "gui/PhotoShare/PhotoSlideShow.h" #include "gui/PhotoShare/PhotoSlideShow.h"
#include "gui/PhotoShare/PhotoDrop.h" #include "gui/PhotoShare/PhotoDrop.h"
#include "gui/gxs/GxsIdDetails.h"
#include <iostream> #include <iostream>
@ -175,16 +176,10 @@ void PhotoSlideShow::loadImage()
if (ptr) if (ptr)
{ {
/* load into the slot */ /* load into the slot */
if (ptr->mThumbnail.data != NULL) if (ptr->mThumbnail.mData != NULL)
{ {
QPixmap qtn; QPixmap qtn;
GxsIdDetails::loadPixmapFromData(ptr->mThumbnail.mData, ptr->mThumbnail.mSize,qtn, GxsIdDetails::ORIGINAL);
// copy the data for Qpixmap to use.
RsPhotoThumbnail tn;
tn.copyFrom(ptr->mThumbnail);
qtn.loadFromData(tn.data, tn.size, tn.type.c_str());
tn.data = 0;
QPixmap sqtn = qtn.scaled(800, 600, Qt::KeepAspectRatio, Qt::SmoothTransformation); QPixmap sqtn = qtn.scaled(800, 600, Qt::KeepAspectRatio, Qt::SmoothTransformation);
ui.imgLabel->setPixmap(sqtn); ui.imgLabel->setPixmap(sqtn);
@ -249,8 +244,8 @@ bool PhotoSlideShow::loadPhotoData(const uint32_t &token)
RsPhotoPhoto& photo = *vit; RsPhotoPhoto& photo = *vit;
RsPhotoPhoto *ptr = new RsPhotoPhoto; RsPhotoPhoto *ptr = new RsPhotoPhoto;
*ptr = photo; *ptr = photo;
ptr->mThumbnail.data = 0;
ptr->mThumbnail.copyFrom(photo.mThumbnail); ptr->mThumbnail = photo.mThumbnail; // copies data.
ptr->mOrder = i++; ptr->mOrder = i++;
mPhotos[photo.mMeta.mMsgId] = ptr; mPhotos[photo.mMeta.mMsgId] = ptr;
mPhotoOrder[ptr->mOrder] = photo.mMeta.mMsgId; mPhotoOrder[ptr->mOrder] = photo.mMeta.mMsgId;

View File

@ -22,6 +22,8 @@
#include <QMessageBox> #include <QMessageBox>
#include <QByteArray> #include <QByteArray>
#include <QStringList> #include <QStringList>
#include <QSignalMapper>
#include "PostedCreatePostDialog.h" #include "PostedCreatePostDialog.h"
#include "ui_PostedCreatePostDialog.h" #include "ui_PostedCreatePostDialog.h"
@ -35,10 +37,13 @@
#include <QBuffer> #include <QBuffer>
#include <iostream> #include <iostream>
#include <gui/RetroShareLink.h>
#include <util/imageutil.h> #include <util/imageutil.h>
#include <gui/RetroShareLink.h> /* View Page */
#define VIEW_POST 1
#define VIEW_IMAGE 2
#define VIEW_LINK 3
PostedCreatePostDialog::PostedCreatePostDialog(TokenQueue* tokenQ, RsPosted *posted, const RsGxsGroupId& grpId, QWidget *parent): PostedCreatePostDialog::PostedCreatePostDialog(TokenQueue* tokenQ, RsPosted *posted, const RsGxsGroupId& grpId, QWidget *parent):
QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint), QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint),
@ -67,6 +72,16 @@ PostedCreatePostDialog::PostedCreatePostDialog(TokenQueue* tokenQ, RsPosted *pos
/* fill in the available OwnIds for signing */ /* fill in the available OwnIds for signing */
ui->idChooser->loadIds(IDCHOOSER_ID_REQUIRED, RsGxsId()); ui->idChooser->loadIds(IDCHOOSER_ID_REQUIRED, RsGxsId());
QSignalMapper *signalMapper = new QSignalMapper(this);
connect(ui->postButton, SIGNAL(clicked()), signalMapper, SLOT(map()));
connect(ui->imageButton, SIGNAL(clicked()), signalMapper, SLOT(map()));
connect(ui->linkButton, SIGNAL(clicked()), signalMapper, SLOT(map()));
signalMapper->setMapping(ui->postButton, VIEW_POST);
signalMapper->setMapping(ui->imageButton, VIEW_IMAGE);
signalMapper->setMapping(ui->linkButton, VIEW_LINK);
connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(setPage(int)));
ui->removeButton->hide(); ui->removeButton->hide();
/* load settings */ /* load settings */
@ -93,11 +108,17 @@ void PostedCreatePostDialog::processSettings(bool load)
// state of ID Chooser combobox // state of ID Chooser combobox
int index = Settings->value("IDChooser", 0).toInt(); int index = Settings->value("IDChooser", 0).toInt();
ui->idChooser->setCurrentIndex(index); ui->idChooser->setCurrentIndex(index);
// load last used Stacked Page
setPage(Settings->value("viewPage", VIEW_POST).toInt());
} else { } else {
// save settings // save settings
// state of ID Chooser combobox // state of ID Chooser combobox
Settings->setValue("IDChooser", ui->idChooser->currentIndex()); Settings->setValue("IDChooser", ui->idChooser->currentIndex());
// store last used Page
Settings->setValue("viewPage", viewMode());
} }
Settings->endGroup(); Settings->endGroup();
@ -222,19 +243,51 @@ void PostedCreatePostDialog::addPicture()
} }
void PostedCreatePostDialog::on_postButton_clicked() int PostedCreatePostDialog::viewMode()
{ {
if (ui->postButton->isChecked()) {
return VIEW_POST;
} else if (ui->imageButton->isChecked()) {
return VIEW_IMAGE;
} else if (ui->linkButton->isChecked()) {
return VIEW_LINK;
}
/* Default */
return VIEW_POST;
}
void PostedCreatePostDialog::setPage(int viewMode)
{
switch (viewMode) {
case VIEW_POST:
ui->stackedWidget->setCurrentIndex(0); ui->stackedWidget->setCurrentIndex(0);
}
void PostedCreatePostDialog::on_imageButton_clicked() ui->postButton->setChecked(true);
{ ui->imageButton->setChecked(false);
ui->linkButton->setChecked(false);
break;
case VIEW_IMAGE:
ui->stackedWidget->setCurrentIndex(1); ui->stackedWidget->setCurrentIndex(1);
}
void PostedCreatePostDialog::on_linkButton_clicked() ui->imageButton->setChecked(true);
{ ui->postButton->setChecked(false);
ui->linkButton->setChecked(false);
break;
case VIEW_LINK:
ui->stackedWidget->setCurrentIndex(2); ui->stackedWidget->setCurrentIndex(2);
ui->linkButton->setChecked(true);
ui->postButton->setChecked(false);
ui->imageButton->setChecked(false);
break;
default:
setPage(VIEW_POST);
return;
}
} }
void PostedCreatePostDialog::on_removeButton_clicked() void PostedCreatePostDialog::on_removeButton_clicked()

View File

@ -52,14 +52,13 @@ private:
private slots: private slots:
void createPost(); void createPost();
void addPicture(); void addPicture();
void on_postButton_clicked();
void on_imageButton_clicked();
void on_linkButton_clicked();
void on_removeButton_clicked(); void on_removeButton_clicked();
void fileHashingFinished(QList<HashedFile> hashedFiles); void fileHashingFinished(QList<HashedFile> hashedFiles);
void setPage(int viewMode);
private: private:
void processSettings(bool load); void processSettings(bool load);
int viewMode();
QString mLink; QString mLink;
QString mNotes; QString mNotes;

View File

@ -246,36 +246,7 @@
<property name="verticalSpacing"> <property name="verticalSpacing">
<number>2</number> <number>2</number>
</property> </property>
<item row="0" column="0" colspan="2"> <item row="1" column="2">
<widget class="QLabel" name="imageLabel">
<property name="maximumSize">
<size>
<width>800</width>
<height>200</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>188</width>
<height>17</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="removeButton"> <widget class="QToolButton" name="removeButton">
<property name="toolTip"> <property name="toolTip">
<string>Remove image</string> <string>Remove image</string>
@ -295,6 +266,42 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>188</width>
<height>17</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="shareimagecheckBox">
<property name="text">
<string>Share Orginal Image</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="imageLabel">
<property name="maximumSize">
<size>
<width>800</width>
<height>200</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>
@ -418,6 +425,9 @@
<height>24</height> <height>24</height>
</size> </size>
</property> </property>
<property name="checkable">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
<item> <item>
@ -435,6 +445,15 @@
<height>24</height> <height>24</height>
</size> </size>
</property> </property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="autoRepeat">
<bool>false</bool>
</property>
<property name="default">
<bool>false</bool>
</property>
</widget> </widget>
</item> </item>
<item> <item>
@ -452,6 +471,12 @@
<height>24</height> <height>24</height>
</size> </size>
</property> </property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="autoDefault">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
<item> <item>

View File

@ -87,13 +87,13 @@ UserNotify *PostedDialog::createUserNotify(QObject *parent)
QString PostedDialog::getHelpString() const QString PostedDialog::getHelpString() const
{ {
QString hlp_str = tr("<h1><img width=\"32\" src=\":/icons/help_64.png\">&nbsp;&nbsp;Posted</h1> \ QString hlp_str = tr("<h1><img width=\"32\" src=\":/icons/help_64.png\">&nbsp;&nbsp;Boards</h1> \
<p>The posted service allows you to share internet links, that spread among Retroshare nodes like forums and \ <p>The Boards service allows you to share images, blog posts & internet links, that spread among Retroshare nodes like forums and \
channels</p> \ channels</p> \
<p>Links can be commented by subscribed users. A promotion system also gives the opportunity to \ <p>Posts can be commented by subscribed users. A promotion system also gives the opportunity to \
enlight important links.</p> \ enlight important links.</p> \
<p>There is no restriction on which links are shared. Be careful when clicking on them.</p>\ <p>There is no restriction on which links are shared. Be careful when clicking on them.</p>\
<p>Posted links are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p>\ <p>Boards are kept for %1 days, and sync-ed over the last %2 days, unless you change this.</p>\
").arg(QString::number(rsPosted->getDefaultStoragePeriod()/86400)).arg(QString::number(rsPosted->getDefaultSyncPeriod()/86400)); ").arg(QString::number(rsPosted->getDefaultStoragePeriod()/86400)).arg(QString::number(rsPosted->getDefaultSyncPeriod()/86400));
return hlp_str ; return hlp_str ;
@ -103,9 +103,9 @@ QString PostedDialog::text(TextType type)
{ {
switch (type) { switch (type) {
case TEXT_NAME: case TEXT_NAME:
return tr("Posted Links"); return tr("Boards");
case TEXT_NEW: case TEXT_NEW:
return tr("Create Topic"); return tr("Create Board");
case TEXT_TODO: case TEXT_TODO:
return "<b>Open points:</b><ul>" return "<b>Open points:</b><ul>"
"<li>Subreddits/tag to posts support" "<li>Subreddits/tag to posts support"
@ -114,13 +114,13 @@ QString PostedDialog::text(TextType type)
"</ul>"; "</ul>";
case TEXT_YOUR_GROUP: case TEXT_YOUR_GROUP:
return tr("My Topics"); return tr("My Boards");
case TEXT_SUBSCRIBED_GROUP: case TEXT_SUBSCRIBED_GROUP:
return tr("Subscribed Topics"); return tr("Subscribed Boards");
case TEXT_POPULAR_GROUP: case TEXT_POPULAR_GROUP:
return tr("Popular Topics"); return tr("Popular Boards");
case TEXT_OTHER_GROUP: case TEXT_OTHER_GROUP:
return tr("Other Topics"); return tr("Other Boards");
} }
return ""; return "";

View File

@ -37,7 +37,7 @@ public:
~PostedDialog(); ~PostedDialog();
virtual QIcon iconPixmap() const { return QIcon(IMAGE_POSTED) ; } //MainPage virtual QIcon iconPixmap() const { return QIcon(IMAGE_POSTED) ; } //MainPage
virtual QString pageName() const { return tr("Links") ; } //MainPage virtual QString pageName() const { return tr("Boards") ; } //MainPage
virtual QString helpText() const { return ""; } //MainPage virtual QString helpText() const { return ""; } //MainPage
protected: protected:

View File

@ -71,20 +71,20 @@ void PostedGroupDialog::initUi()
switch (mode()) switch (mode())
{ {
case MODE_CREATE: case MODE_CREATE:
setUiText(UITYPE_SERVICE_HEADER, tr("Create New Topic")); setUiText(UITYPE_SERVICE_HEADER, tr("Create New Board"));
setUiText(UITYPE_BUTTONBOX_OK, tr("Create")); setUiText(UITYPE_BUTTONBOX_OK, tr("Create"));
break; break;
case MODE_SHOW: case MODE_SHOW:
setUiText(UITYPE_SERVICE_HEADER, tr("Posted Topic")); setUiText(UITYPE_SERVICE_HEADER, tr("Board"));
break; break;
case MODE_EDIT: case MODE_EDIT:
setUiText(UITYPE_SERVICE_HEADER, tr("Edit Topic")); setUiText(UITYPE_SERVICE_HEADER, tr("Edit Board"));
setUiText(UITYPE_BUTTONBOX_OK, tr("Update Topic")); setUiText(UITYPE_BUTTONBOX_OK, tr("Update Board"));
break; break;
} }
setUiText(UITYPE_ADD_ADMINS_CHECKBOX, tr("Add Topic Admins")); setUiText(UITYPE_ADD_ADMINS_CHECKBOX, tr("Add Board Admins"));
setUiText(UITYPE_CONTACTS_DOCK, tr("Select Topic Admins")); setUiText(UITYPE_CONTACTS_DOCK, tr("Select Board Admins"));
} }
QPixmap PostedGroupDialog::serviceImage() QPixmap PostedGroupDialog::serviceImage()

View File

@ -44,7 +44,7 @@
#define DEBUG_POSTED_LIST_WIDGET #define DEBUG_POSTED_LIST_WIDGET
#define TOPIC_DEFAULT_IMAGE ":/icons/png/posted.png" #define BOARD_DEFAULT_IMAGE ":/icons/png/posted.png"
/* View mode */ /* View mode */
#define VIEW_MODE_CLASSIC 1 #define VIEW_MODE_CLASSIC 1
@ -400,13 +400,13 @@ void PostedListWidget::insertPostedDetails(const RsPostedGroup &group)
ui->subscribeToolButton->setHidden(IS_GROUP_SUBSCRIBED(group.mMeta.mSubscribeFlags)) ; ui->subscribeToolButton->setHidden(IS_GROUP_SUBSCRIBED(group.mMeta.mSubscribeFlags)) ;
/* IMAGE */ /* IMAGE */
QPixmap topicImage; QPixmap boardImage;
if (group.mGroupImage.mData != NULL) { if (group.mGroupImage.mData != NULL) {
GxsIdDetails::loadPixmapFromData(group.mGroupImage.mData, group.mGroupImage.mSize, topicImage,GxsIdDetails::ORIGINAL); GxsIdDetails::loadPixmapFromData(group.mGroupImage.mData, group.mGroupImage.mSize, boardImage,GxsIdDetails::ORIGINAL);
} else { } else {
topicImage = QPixmap(TOPIC_DEFAULT_IMAGE); boardImage = QPixmap(BOARD_DEFAULT_IMAGE);
} }
ui->logoLabel->setPixmap(topicImage); ui->logoLabel->setPixmap(boardImage);
ui->namelabel->setText(QString::fromUtf8(group.mMeta.mGroupName.c_str())); ui->namelabel->setText(QString::fromUtf8(group.mMeta.mGroupName.c_str()));
ui->poplabel->setText(QString::number( group.mMeta.mPop)); ui->poplabel->setText(QString::number( group.mMeta.mPop));

View File

@ -89,7 +89,7 @@
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="Posted_images.qrc"> <iconset resource="Posted_images.qrc">
<normaloff>:/images/posted_24.png</normaloff>:/images/posted_24.png</iconset> <normaloff>:/images/write.png</normaloff>:/images/write.png</iconset>
</property> </property>
<property name="iconSize"> <property name="iconSize">
<size> <size>
@ -289,7 +289,7 @@
<string notr="true"/> <string notr="true"/>
</property> </property>
<property name="title"> <property name="title">
<string>Topic Details</string> <string>Board Details</string>
</property> </property>
<property name="flat"> <property name="flat">
<bool>false</bool> <bool>false</bool>

View File

@ -1,16 +1,5 @@
<RCC> <RCC>
<qresource prefix="/" > <qresource prefix="/" >
<file>images/posted_16.png</file>
<file>images/posted_24.png</file>
<file>images/posted_32.png</file>
<file>images/posted_48.png</file>
<file>images/posted_64.png</file>
<file>images/posted_add_24.png</file>
<file>images/posted_add_32.png</file>
<file>images/posted_add_64.png</file>
<file>images/hot_24.png</file>
<file>images/new_24.png</file>
<file>images/posted_32_new.png</file>
<file>images/expand.png</file> <file>images/expand.png</file>
<file>images/decrease.png</file> <file>images/decrease.png</file>
<file>images/down-arrow.png</file> <file>images/down-arrow.png</file>
@ -29,5 +18,6 @@
<file>images/down-hover.png</file> <file>images/down-hover.png</file>
<file>images/up-hover.png</file> <file>images/up-hover.png</file>
<file>images/trashcan.png</file> <file>images/trashcan.png</file>
<file>images/write.png</file>
</qresource> </qresource>
</RCC> </RCC>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 954 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -25,8 +25,6 @@
#include "PulseItem.h" #include "PulseItem.h"
#include <retroshare/rsphoto.h>
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
@ -35,184 +33,21 @@
****/ ****/
/** Constructor */ /** Constructor */
PulseItem::PulseItem(PulseHolder *parent, const RsPhotoAlbum &album, const RsPhotoThumbnail &thumbnail)
:QWidget(NULL), mParent(parent), mType(PHOTO_ITEM_TYPE_ALBUM) PulseItem::PulseItem(PulseHolder *parent, std::string path)
:QWidget(NULL), mParent(parent), mType(0)
{ {
setupUi(this); setupUi(this);
setAttribute ( Qt::WA_DeleteOnClose, true ); setAttribute ( Qt::WA_DeleteOnClose, true );
mDetails = *( (RsPhotoPhoto *) &(album));
updateAlbumText(album);
updateImage(thumbnail);
setSelected(false);
} }
PulseItem::PulseItem(PulseHolder *parent, const RsPhotoPhoto &photo, const RsPhotoThumbnail &thumbnail)
:QWidget(NULL), mParent(parent), mType(PHOTO_ITEM_TYPE_PHOTO)
{
setupUi(this);
setAttribute ( Qt::WA_DeleteOnClose, true );
mDetails = *( (RsPhotoPhoto *) &(photo));
updatePhotoText(photo);
updateImage(thumbnail);
setSelected(false);
}
PulseItem::PulseItem(PulseHolder *parent, std::string path) // for new photos.
:QWidget(NULL), mParent(parent), mType(PHOTO_ITEM_TYPE_NEW)
{
setupUi(this);
setAttribute ( Qt::WA_DeleteOnClose, true );
#if 0
QString dummyString("dummytext");
titleLabel->setText(QString("NEW PHOTO"));
fromBoldLabel->setText(QString("From:"));
fromLabel->setText(QString("Ourselves"));
statusBoldLabel->setText(QString("Status:"));
statusLabel->setText(QString("new photo"));
dateBoldLabel->setText(QString("Date:"));
dateLabel->setText(QString("now"));
int width = 120;
int height = 120;
//QPixmap qtn = QPixmap(QString::fromStdString(path)).scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
QPixmap qtn = QPixmap(QString::fromStdString(path)).scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation);
imgLabel->setPixmap(qtn);
setSelected(false);
#endif
}
void PulseItem::updateAlbumText(const RsPhotoAlbum &album)
{
#if 0
QString dummyString("dummytext");
titleLabel->setText(QString("TITLE"));
fromBoldLabel->setText(QString("From:"));
fromLabel->setText(QString("Unknown"));
statusBoldLabel->setText(QString("Status:"));
statusLabel->setText(QString("new photo"));
dateBoldLabel->setText(QString("Date:"));
dateLabel->setText(QString("now"));
//QDateTime qtime;
//qtime.setTime_t(msg.ts);
//QString timestamp = qtime.toString("dd.MMMM yyyy hh:mm");
//timestamplabel->setText(timestamp);
dateBoldLabel->setText(dummyString);
dateLabel->setText(dummyString);
#endif
}
void PulseItem::updatePhotoText(const RsPhotoPhoto &photo)
{
#if 0
QString dummyString("dummytext");
titleLabel->setText(QString("TITLE"));
fromBoldLabel->setText(QString("From:"));
fromLabel->setText(QString("Unknown"));
statusBoldLabel->setText(QString("Status:"));
statusLabel->setText(QString("new photo"));
dateBoldLabel->setText(QString("Date:"));
dateLabel->setText(QString("now"));
#endif
}
void PulseItem::updateImage(const RsPhotoThumbnail &thumbnail)
{
#if 0
if (thumbnail.data != NULL)
{
QPixmap qtn;
qtn.loadFromData(thumbnail.data, thumbnail.size, thumbnail.type.c_str());
imgLabel->setPixmap(qtn);
}
#endif
}
bool PulseItem::getPhotoThumbnail(RsPhotoThumbnail &nail)
{
#if 0
const QPixmap *tmppix = imgLabel->pixmap();
QByteArray ba;
QBuffer buffer(&ba);
if(!tmppix->isNull())
{
// send chan image
buffer.open(QIODevice::WriteOnly);
tmppix->save(&buffer, "PNG"); // writes image into ba in PNG format
RsPhotoThumbnail tmpnail;
tmpnail.data = (uint8_t *) ba.data();
tmpnail.size = ba.size();
nail.copyFrom(tmpnail);
return true;
}
nail.data = NULL;
nail.size = 0;
#endif
return false;
}
void PulseItem::removeItem() void PulseItem::removeItem()
{ {
#if 0
#ifdef DEBUG_ITEM
std::cerr << "PulseItem::removeItem()";
std::cerr << std::endl;
#endif
hide();
if (mParent)
{
mParent->deletePulseItem(this, mType);
} }
#endif
}
void PulseItem::setSelected(bool on) void PulseItem::setSelected(bool on)
{ {
#if 0
mSelected = on;
if (mSelected)
{
mParent->notifySelection(this, mType);
frame->setStyleSheet("QFrame#frame{border: 2px solid #55CC55;\nbackground: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #55EE55, stop: 1 #CCCCCC);\nborder-radius: 10px}");
}
else
{
frame->setStyleSheet("QFrame#frame{border: 2px solid #CCCCCC;\nbackground: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #EEEEEE, stop: 1 #CCCCCC);\nborder-radius: 10px}");
}
update();
#endif
} }
bool PulseItem::isSelected() bool PulseItem::isSelected()
@ -220,7 +55,6 @@ bool PulseItem::isSelected()
return mSelected; return mSelected;
} }
void PulseItem::mousePressEvent(QMouseEvent *event) void PulseItem::mousePressEvent(QMouseEvent *event)
{ {
/* We can be very cunning here? /* We can be very cunning here?
@ -239,13 +73,8 @@ void PulseItem::mousePressEvent(QMouseEvent *event)
QWidget::mousePressEvent(event); QWidget::mousePressEvent(event);
} }
const QPixmap *PulseItem::getPixmap() const QPixmap *PulseItem::getPixmap()
{ {
#if 0
return imgLabel->pixmap();
#endif
return NULL; return NULL;
} }

View File

@ -23,8 +23,6 @@
#include "ui_PulseItem.h" #include "ui_PulseItem.h"
#include <retroshare/rsphoto.h>
class PulseItem; class PulseItem;
class PulseHolder class PulseHolder
@ -34,21 +32,12 @@ virtual void deletePulseItem(PulseItem *, uint32_t ptype) = 0;
virtual void notifySelection(PulseItem *item, int ptype) = 0; virtual void notifySelection(PulseItem *item, int ptype) = 0;
}; };
#define PHOTO_ITEM_TYPE_ALBUM 0x0001
#define PHOTO_ITEM_TYPE_PHOTO 0x0002
#define PHOTO_ITEM_TYPE_NEW 0x0003
class PulseItem : public QWidget, private Ui::PulseItem class PulseItem : public QWidget, private Ui::PulseItem
{ {
Q_OBJECT Q_OBJECT
public: public:
PulseItem(PulseHolder *parent, const RsPhotoAlbum &album, const RsPhotoThumbnail &thumbnail); PulseItem(PulseHolder *parent, std::string url);
PulseItem(PulseHolder *parent, const RsPhotoPhoto &photo, const RsPhotoThumbnail &thumbnail);
PulseItem(PulseHolder *parent, std::string url); // for new photos.
bool getPhotoThumbnail(RsPhotoThumbnail &nail);
void removeItem(); void removeItem();
@ -57,27 +46,14 @@ public:
const QPixmap *getPixmap(); const QPixmap *getPixmap();
// details are public - so that can be easily edited.
RsPhotoPhoto mDetails;
//private slots:
protected: protected:
void mousePressEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event);
private: private:
void updateAlbumText(const RsPhotoAlbum &album);
void updatePhotoText(const RsPhotoPhoto &photo);
void updateImage(const RsPhotoThumbnail &thumbnail);
PulseHolder *mParent; PulseHolder *mParent;
uint32_t mType; uint32_t mType;
bool mSelected; bool mSelected;
}; };
#endif #endif

View File

@ -32,7 +32,7 @@
#include <map> #include <map>
#define IMAGE_WIKI ":/images/wikibook_32.png" #define IMAGE_WIKI ":/icons/png/wiki.png"
class WikiAddDialog; class WikiAddDialog;
class WikiEditDialog; class WikiEditDialog;

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1433</width> <width>922</width>
<height>541</height> <height>187</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gxsChannelPostItem_GLayout"> <layout class="QGridLayout" name="gxsChannelPostItem_GLayout">
@ -127,6 +127,19 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<layout class="QHBoxLayout" name="subjectHLayout"/> <layout class="QHBoxLayout" name="subjectHLayout"/>
</item> </item>

View File

@ -141,15 +141,15 @@ void PostedGroupItem::fill()
GxsIdDetails::loadPixmapFromData(mGroup.mGroupImage.mData, mGroup.mGroupImage.mSize, postedImage,GxsIdDetails::ORIGINAL); GxsIdDetails::loadPixmapFromData(mGroup.mGroupImage.mData, mGroup.mGroupImage.mSize, postedImage,GxsIdDetails::ORIGINAL);
ui->logoLabel->setPixmap(QPixmap(postedImage)); ui->logoLabel->setPixmap(QPixmap(postedImage));
} else { } else {
ui->logoLabel->setPixmap(QPixmap(":/images/posted_64.png")); ui->logoLabel->setPixmap(QPixmap(":/icons/png/posted.png"));
} }
//TODO - nice icon for subscribed group //TODO - nice icon for subscribed group
// if (IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags)) { // if (IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags)) {
// ui->logoLabel->setPixmap(QPixmap(":/images/posted_64.png")); // ui->logoLabel->setPixmap(QPixmap(":/icons/png/posted.png"));
// } else { // } else {
// ui->logoLabel->setPixmap(QPixmap(":/images/posted_64.png")); // ui->logoLabel->setPixmap(QPixmap(":/icons/png/posted.png"));
// } // }
if (IS_GROUP_SUBSCRIBED(mGroup.mMeta.mSubscribeFlags)) { if (IS_GROUP_SUBSCRIBED(mGroup.mMeta.mSubscribeFlags)) {
@ -160,11 +160,11 @@ void PostedGroupItem::fill()
// if (mIsNew) // if (mIsNew)
// { // {
ui->titleLabel->setText(tr("New Posted")); ui->titleLabel->setText(tr("New Board"));
// } // }
// else // else
// { // {
// ui->titleLabel->setText(tr("Updated Posted")); // ui->titleLabel->setText(tr("Updated Board"));
// } // }
if (mIsHome) if (mIsHome)

View File

@ -125,7 +125,10 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="../Posted/Posted_images.qrc">:/images/posted_64.png</pixmap> <pixmap resource="../icons.qrc">:/icons/png/posted.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
@ -147,7 +150,7 @@
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string notr="true">Posted</string> <string notr="true">Board</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -298,7 +301,7 @@
<item> <item>
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">
<property name="title"> <property name="title">
<string>Posted Description</string> <string>Board Description</string>
</property> </property>
<layout class="QHBoxLayout"> <layout class="QHBoxLayout">
<item> <item>
@ -321,7 +324,7 @@
</property> </property>
<property name="text"> <property name="text">
<string notr="true">Description <string notr="true">Description
of Posted</string> of Board</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -160,6 +160,15 @@ void GxsGroupDialog::init()
Settings->loadWidgetInformation(this); Settings->loadWidgetInformation(this);
} }
void GxsGroupDialog::injectExtraWidget(QWidget *widget)
{
// add extra widget into layout.
QVBoxLayout *vbox = new QVBoxLayout();
vbox->addWidget(widget);
vbox->addStretch(1);
ui.extraFrame->setLayout(vbox);
}
QIcon GxsGroupDialog::serviceWindowIcon() QIcon GxsGroupDialog::serviceWindowIcon()
{ {
return qApp->windowIcon(); return qApp->windowIcon();

View File

@ -172,6 +172,13 @@ protected:
virtual QPixmap serviceImage() = 0; virtual QPixmap serviceImage() = 0;
virtual QIcon serviceWindowIcon(); virtual QIcon serviceWindowIcon();
/*!
* Inject Extra Widget for additional Group configuration options.
* NB: These are only inserted for createMode currently.
* @param widget Addtional widget which is added to extraFrame.
*/
void injectExtraWidget(QWidget *widget);
/*! /*!
* \brief setUiToolTip/setUiText * \brief setUiToolTip/setUiText
* Sets the text and tooltip of some parts of the UI * Sets the text and tooltip of some parts of the UI

View File

@ -93,9 +93,9 @@ void GroupShareKey::setTyp()
if (!rsPosted) if (!rsPosted)
return; return;
ui->headerFrame->setHeaderImage(QPixmap(":/images/posted_64.png")); ui->headerFrame->setHeaderImage(QPixmap(":/icons/png/posted.png"));
ui->headerFrame->setHeaderText(tr("Share topic admin permissions")); ui->headerFrame->setHeaderText(tr("Share board admin permissions"));
ui->sharekeyinfo_label->setText(tr("You can allow your friends to edit the topic. Select them in the list below. Note: it is not possible to revoke Posted admin permissions.")); ui->sharekeyinfo_label->setText(tr("You can allow your friends to edit the board. Select them in the list below. Note: it is not possible to revoke Board admin permissions."));
} }
else else

View File

@ -287,9 +287,11 @@
<file>icons/png/newsfeed2.png</file> <file>icons/png/newsfeed2.png</file>
<file>icons/png/postedlinks.png</file> <file>icons/png/postedlinks.png</file>
<file>icons/png/people2.png</file> <file>icons/png/people2.png</file>
<file>icons/png/photo.png</file>
<file>icons/png/bandwidth.png</file> <file>icons/png/bandwidth.png</file>
<file>icons/png/options2.png</file> <file>icons/png/options2.png</file>
<file>icons/png/exit2.png</file> <file>icons/png/exit2.png</file>
<file>icons/png/wiki.png</file>
<file>icons/svg/addstickers.svg</file> <file>icons/svg/addstickers.svg</file>
<file>icons/png/addstickers.png</file> <file>icons/png/addstickers.png</file>
<file>icons/textedit/bold.png</file> <file>icons/textedit/bold.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,10 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 477.867 477.867" style="enable-background:new 0 0 477.867 477.867;" xml:space="preserve" width="512px" height="512px"><g transform="matrix(0.922745 0 0 0.922745 18.4589 18.4589)"><g>
<g>
<path d="M426.667,68.267H51.2c-28.277,0-51.2,22.923-51.2,51.2V358.4c0,28.277,22.923,51.2,51.2,51.2h375.467 c28.277,0,51.2-22.923,51.2-51.2V119.467C477.867,91.19,454.944,68.267,426.667,68.267z M443.733,266.001L336.333,158.601 c-6.664-6.663-17.468-6.663-24.132,0L170.667,300.134l-56.201-56.201c-6.664-6.663-17.468-6.663-24.132,0l-56.201,56.201V119.467 c0-9.426,7.641-17.067,17.067-17.067h375.467c9.426,0,17.067,7.641,17.067,17.067V266.001z" data-original="#000000" class="active-path" data-old_color="#000000" fill="#039BD5"/>
</g>
</g><g>
<g>
<circle cx="153.6" cy="187.733" r="51.2" data-original="#000000" class="active-path" data-old_color="#000000" fill="#039BD5"/>
</g>
</g></g> </svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,14 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve" width="512px" height="512px" class=""><g transform="matrix(0.895338 0 0 0.895338 26.7934 26.7934)"><g>
<g>
<path d="M467,0H361v120h151V45C512,20.186,491.814,0,467,0z" data-original="#000000" class="active-path" data-old_color="#000000" fill="#039BD5"/>
</g>
</g><g>
<g>
<path d="M45,0C20.186,0,0,20.186,0,45v75h331V0H45z M106,90H76c-8.291,0-15-6.709-15-15s6.709-15,15-15h30c8.291,0,15,6.709,15,15 S114.291,90,106,90z M196,90h-30c-8.291,0-15-6.709-15-15s6.709-15,15-15h30c8.291,0,15,6.709,15,15S204.291,90,196,90z M286,90 h-30c-8.291,0-15-6.709-15-15s6.709-15,15-15h30c8.291,0,15,6.709,15,15S294.291,90,286,90z" data-original="#000000" class="active-path" data-old_color="#000000" fill="#039BD5"/>
</g>
</g><g>
<g>
<path d="M0,150v317c0,24.814,20.186,45,45,45h422c24.814,0,45-20.186,45-45V150H0z M406,240h-19.195l-56.581,170.746 C328.188,416.869,322.46,421,316,421c-6.46,0-12.188-4.131-14.224-10.254L256,272.432l-45.776,138.314 c-4.072,12.246-24.375,12.246-28.447,0L125.195,240H106c-8.291,0-15-6.709-15-15s6.709-15,15-15h60c8.291,0,15,6.709,15,15 s-6.709,15-15,15h-9.194L196,358.568L235.194,240H226c-8.291,0-15-6.709-15-15s6.709-15,15-15h60c8.291,0,15,6.709,15,15 s-6.709,15-15,15h-9.194L316,358.568L355.194,240H346c-8.291,0-15-6.709-15-15s6.709-15,15-15h60c8.291,0,15,6.709,15,15 S414.291,240,406,240z" data-original="#000000" class="active-path" data-old_color="#000000" fill="#039BD5"/>
</g>
</g></g> </svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -30,7 +30,7 @@ PostedPage::PostedPage(QWidget * parent, Qt::WindowFlags flags)
setAttribute(Qt::WA_QuitOnClose, false); setAttribute(Qt::WA_QuitOnClose, false);
/* Initialize GroupFrameSettingsWidget */ /* Initialize GroupFrameSettingsWidget */
ui->groupFrameSettingsWidget->setOpenAllInNewTabText(tr("Open each topic in a new tab")); ui->groupFrameSettingsWidget->setOpenAllInNewTabText(tr("Open each board in a new tab"));
ui->groupFrameSettingsWidget->setType(GroupFrameSettings::Posted); ui->groupFrameSettingsWidget->setType(GroupFrameSettings::Posted);
} }

View File

@ -39,7 +39,7 @@ public:
virtual void load(); virtual void load();
virtual QPixmap iconPixmap() const { return QPixmap(":/icons/settings/posted.svg") ; } virtual QPixmap iconPixmap() const { return QPixmap(":/icons/settings/posted.svg") ; }
virtual QString pageName() const { return tr("Links") ; } virtual QString pageName() const { return tr("Boards") ; }
virtual QString helpText() const { return ""; } virtual QString helpText() const { return ""; }
private: private:

View File

@ -1154,6 +1154,8 @@ gxsphotoshare {
DEFINES += RS_USE_PHOTO # enable in MainWindow DEFINES += RS_USE_PHOTO # enable in MainWindow
HEADERS += \ HEADERS += \
gui/PhotoShare/AlbumGroupDialog.h \
gui/PhotoShare/AlbumExtra.h \
gui/PhotoShare/PhotoDrop.h \ gui/PhotoShare/PhotoDrop.h \
gui/PhotoShare/AlbumItem.h \ gui/PhotoShare/AlbumItem.h \
gui/PhotoShare/AlbumDialog.h \ gui/PhotoShare/AlbumDialog.h \
@ -1167,6 +1169,7 @@ gxsphotoshare {
gui/PhotoShare/AddCommentDialog.h gui/PhotoShare/AddCommentDialog.h
FORMS += \ FORMS += \
gui/PhotoShare/AlbumExtra.ui \
gui/PhotoShare/PhotoItem.ui \ gui/PhotoShare/PhotoItem.ui \
gui/PhotoShare/PhotoDialog.ui \ gui/PhotoShare/PhotoDialog.ui \
gui/PhotoShare/AlbumItem.ui \ gui/PhotoShare/AlbumItem.ui \
@ -1178,6 +1181,8 @@ gxsphotoshare {
gui/PhotoShare/AddCommentDialog.ui gui/PhotoShare/AddCommentDialog.ui
SOURCES += \ SOURCES += \
gui/PhotoShare/AlbumGroupDialog.cpp \
gui/PhotoShare/AlbumExtra.cpp \
gui/PhotoShare/PhotoItem.cpp \ gui/PhotoShare/PhotoItem.cpp \
gui/PhotoShare/PhotoDialog.cpp \ gui/PhotoShare/PhotoDialog.cpp \
gui/PhotoShare/PhotoDrop.cpp \ gui/PhotoShare/PhotoDrop.cpp \

View File

@ -111,6 +111,19 @@ no_direct_chat:CONFIG -= direct_chat
CONFIG *= bitdht CONFIG *= bitdht
no_bitdht:CONFIG -= bitdht no_bitdht:CONFIG -= bitdht
# The DHT stunner is used to determine the NAT type using other RS DHT peers and the STUN (Session Traversal Utilities for NAT) protocol.
# To disable DHT stunner append the following assignation to qmake command line
# "CONFIG+=no_use_dht_stunner"
CONFIG *= use_dht_stunner
no_use_dht_stunner:CONFIG -= use_dht_stunner
# The DHT stunner can be used to figure out our external IP. As this purely relying on random DHT peers that answer our request, it can easily be abused.
# Therefore, it is turned off by default.
# To enable external ip determination (additionally) based on the dht stunner append the following assignation to qmake
# command line "CONFIG+=use_dht_stunner_ext_ip"
CONFIG *= no_use_dht_stunner_ext_ip
use_dht_stunner_ext_ip:CONFIG -= no_use_dht_stunner_ext_ip
# To select your MacOsX version append the following assignation to qmake # To select your MacOsX version append the following assignation to qmake
# command line "CONFIG+=rs_macos10.11" where 10.11 depends your version # command line "CONFIG+=rs_macos10.11" where 10.11 depends your version
macx:CONFIG *= rs_macos10.11 macx:CONFIG *= rs_macos10.11
@ -492,6 +505,14 @@ rs_gxs_trans {
bitdht { bitdht {
DEFINES *= RS_USE_BITDHT DEFINES *= RS_USE_BITDHT
use_dht_stunner {
CONFIG *= useDhtStunner
use_dht_stunner_ext_ip {
DEFINES *= ALLOW_DHT_STUNNER
}
}
} }
direct_chat { direct_chat {