2018-11-15 21:49:12 +01:00
/*******************************************************************************
* retroshare - gui / src / gui / gxschannels / GxsChannelPostsWidget . cpp *
* *
* Copyright 2013 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/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-05-04 22:59:06 +00:00
2014-08-01 14:49:58 +00:00
# include <QDateTime>
2014-08-05 20:50:55 +00:00
# include <QSignalMapper>
2014-08-01 14:49:58 +00:00
2016-04-11 22:42:02 -04:00
# include "retroshare/rsgxscircles.h"
2014-05-04 22:59:06 +00:00
# include "GxsChannelPostsWidget.h"
# include "ui_GxsChannelPostsWidget.h"
# include "gui/feeds/GxsChannelPostItem.h"
# include "gui/gxschannels/CreateGxsChannelMsg.h"
# include "gui/common/UIStateHelper.h"
2014-05-27 06:57:45 +00:00
# include "gui/settings/rsharesettings.h"
# include "gui/feeds/SubFileItem.h"
2014-08-06 17:41:22 +00:00
# include "gui/notifyqt.h"
2018-12-25 19:14:48 +01:00
# include "gui/RetroShareLink.h"
# include "util/HandleRichText.h"
2017-01-10 01:18:35 +03:00
# include "util/DateTime.h"
2018-11-01 14:51:57 +01:00
# include "util/qtthreadsutils.h"
# include <algorithm>
2014-05-05 21:53:47 +00:00
2014-05-04 22:59:06 +00:00
# define CHAN_DEFAULT_IMAGE ": / images / channels.png"
2014-08-01 14:49:58 +00:00
# define ROLE_PUBLISH FEED_TREEWIDGET_SORTROLE
2014-05-04 22:59:06 +00:00
/****
* # define DEBUG_CHANNEL
* * */
2014-08-05 20:50:55 +00:00
/* View mode */
# define VIEW_MODE_FEEDS 1
# define VIEW_MODE_FILES 2
2014-05-27 06:57:45 +00:00
2014-05-04 22:59:06 +00:00
/** Constructor */
2014-05-06 20:19:04 +00:00
GxsChannelPostsWidget : : GxsChannelPostsWidget ( const RsGxsGroupId & channelId , QWidget * parent ) :
2014-07-23 18:51:56 +00:00
GxsMessageFramePostWidget ( rsGxsChannels , parent ) ,
2014-05-04 22:59:06 +00:00
ui ( new Ui : : GxsChannelPostsWidget )
{
/* Invoke the Qt Designer generated object setup routine */
ui - > setupUi ( this ) ;
2014-08-01 14:49:58 +00:00
2014-05-04 22:59:06 +00:00
/* Setup UI helper */
2015-08-13 15:22:48 +02:00
mStateHelper - > addWidget ( mTokenTypeAllPosts , ui - > progressBar , UISTATE_LOADING_VISIBLE ) ;
mStateHelper - > addWidget ( mTokenTypeAllPosts , ui - > loadingLabel , UISTATE_LOADING_VISIBLE ) ;
mStateHelper - > addWidget ( mTokenTypeAllPosts , ui - > filterLineEdit ) ;
2014-08-01 18:54:55 +00:00
2015-08-13 15:22:48 +02:00
mStateHelper - > addWidget ( mTokenTypePosts , ui - > loadingLabel , UISTATE_LOADING_VISIBLE ) ;
2014-05-04 22:59:06 +00:00
2014-07-23 18:51:56 +00:00
mStateHelper - > addLoadPlaceholder ( mTokenTypeGroupData , ui - > nameLabel ) ;
2014-05-04 22:59:06 +00:00
2014-07-23 18:51:56 +00:00
mStateHelper - > addWidget ( mTokenTypeGroupData , ui - > postButton ) ;
mStateHelper - > addWidget ( mTokenTypeGroupData , ui - > logoLabel ) ;
mStateHelper - > addWidget ( mTokenTypeGroupData , ui - > subscribeToolButton ) ;
2014-05-04 22:59:06 +00:00
2014-08-06 17:41:22 +00:00
/* Connect signals */
2014-05-04 22:59:06 +00:00
connect ( ui - > postButton , SIGNAL ( clicked ( ) ) , this , SLOT ( createMsg ( ) ) ) ;
2014-07-05 18:33:11 +00:00
connect ( ui - > subscribeToolButton , SIGNAL ( subscribe ( bool ) ) , this , SLOT ( subscribeGroup ( bool ) ) ) ;
2014-08-06 17:41:22 +00:00
connect ( NotifyQt : : getInstance ( ) , SIGNAL ( settingsChanged ( ) ) , this , SLOT ( settingsChanged ( ) ) ) ;
2014-07-05 18:33:11 +00:00
2017-10-22 15:55:08 +03:00
ui - > postButton - > setText ( tr ( " Add new post " ) ) ;
2014-05-27 06:57:45 +00:00
/* add filter actions */
ui - > filterLineEdit - > addFilter ( QIcon ( ) , tr ( " Title " ) , FILTER_TITLE , tr ( " Search Title " ) ) ;
ui - > filterLineEdit - > addFilter ( QIcon ( ) , tr ( " Message " ) , FILTER_MSG , tr ( " Search Message " ) ) ;
ui - > filterLineEdit - > addFilter ( QIcon ( ) , tr ( " Filename " ) , FILTER_FILE_NAME , tr ( " Search Filename " ) ) ;
2014-08-01 14:49:58 +00:00
connect ( ui - > filterLineEdit , SIGNAL ( textChanged ( QString ) ) , ui - > feedWidget , SLOT ( setFilterText ( QString ) ) ) ;
2014-08-05 20:50:55 +00:00
connect ( ui - > filterLineEdit , SIGNAL ( textChanged ( QString ) ) , ui - > fileWidget , SLOT ( setFilterText ( QString ) ) ) ;
2014-05-27 06:57:45 +00:00
connect ( ui - > filterLineEdit , SIGNAL ( filterChanged ( int ) ) , this , SLOT ( filterChanged ( int ) ) ) ;
2014-05-04 22:59:06 +00:00
2014-08-05 20:50:55 +00:00
/* Initialize view button */
//setViewMode(VIEW_MODE_FEEDS); see processSettings
2015-02-09 22:11:19 +00:00
ui - > infoWidget - > hide ( ) ;
2014-08-05 20:50:55 +00:00
QSignalMapper * signalMapper = new QSignalMapper ( this ) ;
connect ( ui - > feedToolButton , SIGNAL ( clicked ( ) ) , signalMapper , SLOT ( map ( ) ) ) ;
connect ( ui - > fileToolButton , SIGNAL ( clicked ( ) ) , signalMapper , SLOT ( map ( ) ) ) ;
signalMapper - > setMapping ( ui - > feedToolButton , VIEW_MODE_FEEDS ) ;
signalMapper - > setMapping ( ui - > fileToolButton , VIEW_MODE_FILES ) ;
connect ( signalMapper , SIGNAL ( mapped ( int ) ) , this , SLOT ( setViewMode ( int ) ) ) ;
2014-05-04 22:59:06 +00:00
/*************** Setup Left Hand Side (List of Channels) ****************/
2014-05-06 20:55:30 +00:00
ui - > loadingLabel - > hide ( ) ;
2014-05-04 22:59:06 +00:00
ui - > progressBar - > hide ( ) ;
ui - > nameLabel - > setMinimumWidth ( 20 ) ;
2014-08-01 14:49:58 +00:00
/* Initialize feed widget */
ui - > feedWidget - > setSortRole ( ROLE_PUBLISH , Qt : : DescendingOrder ) ;
ui - > feedWidget - > setFilterCallback ( filterItem ) ;
2014-05-27 06:57:45 +00:00
2014-05-04 22:59:06 +00:00
/* load settings */
processSettings ( true ) ;
2014-07-05 18:33:11 +00:00
/* Initialize subscribe button */
QIcon icon ;
icon . addPixmap ( QPixmap ( " :/images/redled.png " ) , QIcon : : Normal , QIcon : : On ) ;
icon . addPixmap ( QPixmap ( " :/images/start.png " ) , QIcon : : Normal , QIcon : : Off ) ;
mAutoDownloadAction = new QAction ( icon , " " , this ) ;
mAutoDownloadAction - > setCheckable ( true ) ;
connect ( mAutoDownloadAction , SIGNAL ( triggered ( ) ) , this , SLOT ( toggleAutoDownload ( ) ) ) ;
ui - > subscribeToolButton - > addSubscribedAction ( mAutoDownloadAction ) ;
2014-05-04 22:59:06 +00:00
/* Initialize GUI */
2014-07-05 18:33:11 +00:00
setAutoDownload ( false ) ;
2014-08-06 17:41:22 +00:00
settingsChanged ( ) ;
2014-05-04 22:59:06 +00:00
setGroupId ( channelId ) ;
}
GxsChannelPostsWidget : : ~ GxsChannelPostsWidget ( )
{
// save settings
processSettings ( false ) ;
2014-07-05 18:33:11 +00:00
delete ( mAutoDownloadAction ) ;
2014-07-24 16:52:11 +00:00
delete ui ;
2014-05-04 22:59:06 +00:00
}
2014-08-01 14:49:58 +00:00
void GxsChannelPostsWidget : : processSettings ( bool load )
2014-05-04 22:59:06 +00:00
{
2014-08-01 14:49:58 +00:00
Settings - > beginGroup ( QString ( " ChannelPostsWidget " ) ) ;
if ( load ) {
// load settings
2015-02-09 22:11:19 +00:00
/* Filter */
2014-08-01 14:49:58 +00:00
ui - > filterLineEdit - > setCurrentFilter ( Settings - > value ( " filter " , FILTER_TITLE ) . toInt ( ) ) ;
2015-02-09 22:11:19 +00:00
/* View mode */
2014-08-05 20:50:55 +00:00
setViewMode ( Settings - > value ( " viewMode " , VIEW_MODE_FEEDS ) . toInt ( ) ) ;
2014-08-01 14:49:58 +00:00
} else {
// save settings
2015-02-09 22:11:19 +00:00
/* Filter */
Settings - > setValue ( " filter " , ui - > filterLineEdit - > currentFilter ( ) ) ;
/* View mode */
Settings - > setValue ( " viewMode " , viewMode ( ) ) ;
2014-08-01 14:49:58 +00:00
}
Settings - > endGroup ( ) ;
2014-05-04 22:59:06 +00:00
}
2014-08-06 17:41:22 +00:00
void GxsChannelPostsWidget : : settingsChanged ( )
{
mUseThread = Settings - > getChannelLoadThread ( ) ;
mStateHelper - > setWidgetVisible ( ui - > progressBar , mUseThread ) ;
}
2014-07-23 18:51:56 +00:00
void GxsChannelPostsWidget : : groupNameChanged ( const QString & name )
2014-05-04 22:59:06 +00:00
{
2014-07-23 18:51:56 +00:00
if ( groupId ( ) . isNull ( ) ) {
ui - > nameLabel - > setText ( tr ( " No Channel Selected " ) ) ;
ui - > logoLabel - > setPixmap ( QPixmap ( " :/images/channels.png " ) ) ;
} else {
ui - > nameLabel - > setText ( name ) ;
2014-05-04 22:59:06 +00:00
}
}
QIcon GxsChannelPostsWidget : : groupIcon ( )
{
2015-08-13 15:22:48 +02:00
if ( mStateHelper - > isLoading ( mTokenTypeGroupData ) | | mStateHelper - > isLoading ( mTokenTypeAllPosts ) ) {
2014-05-04 22:59:06 +00:00
return QIcon ( " :/images/kalarm.png " ) ;
}
// if (mNewCount) {
// return QIcon(":/images/message-state-new.png");
// }
return QIcon ( ) ;
}
/*************************************************************************************/
/*************************************************************************************/
/*************************************************************************************/
QScrollArea * GxsChannelPostsWidget : : getScrollArea ( )
{
2014-08-01 14:49:58 +00:00
return NULL ;
2014-05-04 22:59:06 +00:00
}
void GxsChannelPostsWidget : : deleteFeedItem ( QWidget * /*item*/ , uint32_t /*type*/ )
{
}
void GxsChannelPostsWidget : : openChat ( const RsPeerId & /*peerId*/ )
{
}
// Callback from Widget->FeedHolder->ServiceDialog->CommentContainer->CommentDialog,
2017-05-18 22:31:52 +02:00
void GxsChannelPostsWidget : : openComments ( uint32_t /*type*/ , const RsGxsGroupId & groupId , const QVector < RsGxsMessageId > & msg_versions , const RsGxsMessageId & msgId , const QString & title )
2014-05-04 22:59:06 +00:00
{
2017-05-18 22:31:52 +02:00
emit loadComment ( groupId , msg_versions , msgId , title ) ;
2014-05-04 22:59:06 +00:00
}
void GxsChannelPostsWidget : : createMsg ( )
{
2014-07-23 18:51:56 +00:00
if ( groupId ( ) . isNull ( ) ) {
2014-05-04 22:59:06 +00:00
return ;
}
2014-07-23 18:51:56 +00:00
if ( ! IS_GROUP_SUBSCRIBED ( subscribeFlags ( ) ) ) {
2014-07-22 15:04:36 +00:00
return ;
}
2014-07-23 18:51:56 +00:00
CreateGxsChannelMsg * msgDialog = new CreateGxsChannelMsg ( groupId ( ) ) ;
2014-05-04 22:59:06 +00:00
msgDialog - > show ( ) ;
/* window will destroy itself! */
}
void GxsChannelPostsWidget : : insertChannelDetails ( const RsGxsChannelGroup & group )
{
/* IMAGE */
QPixmap chanImage ;
if ( group . mImage . mData ! = NULL ) {
chanImage . loadFromData ( group . mImage . mData , group . mImage . mSize , " PNG " ) ;
} else {
chanImage = QPixmap ( CHAN_DEFAULT_IMAGE ) ;
}
ui - > logoLabel - > setPixmap ( chanImage ) ;
2015-02-09 22:11:19 +00:00
ui - > subscribersLabel - > setText ( QString : : number ( group . mMeta . mPop ) ) ;
2014-05-04 22:59:06 +00:00
2014-07-23 18:51:56 +00:00
if ( group . mMeta . mSubscribeFlags & GXS_SERV : : GROUP_SUBSCRIBE_PUBLISH )
2014-05-04 22:59:06 +00:00
{
mStateHelper - > setWidgetEnabled ( ui - > postButton , true ) ;
}
else
{
mStateHelper - > setWidgetEnabled ( ui - > postButton , false ) ;
}
2014-07-23 18:51:56 +00:00
ui - > subscribeToolButton - > setSubscribed ( IS_GROUP_SUBSCRIBED ( group . mMeta . mSubscribeFlags ) ) ;
2019-01-13 15:38:26 +01:00
mStateHelper - > setWidgetEnabled ( ui - > subscribeToolButton , true ) ;
2014-07-05 18:33:11 +00:00
2015-07-07 00:52:52 +00:00
bool autoDownload ;
rsGxsChannels - > getChannelAutoDownload ( group . mMeta . mGroupId , autoDownload ) ;
2014-07-05 18:33:11 +00:00
setAutoDownload ( autoDownload ) ;
2018-12-25 19:14:48 +01:00
RetroShareLink link ;
2015-02-09 22:11:19 +00:00
if ( IS_GROUP_SUBSCRIBED ( group . mMeta . mSubscribeFlags ) ) {
ui - > feedToolButton - > setEnabled ( true ) ;
ui - > fileToolButton - > setEnabled ( true ) ;
ui - > infoWidget - > hide ( ) ;
setViewMode ( viewMode ( ) ) ;
ui - > infoPosts - > clear ( ) ;
ui - > infoDescription - > clear ( ) ;
} else {
2017-01-11 22:44:27 +03:00
ui - > infoPosts - > setText ( QString : : number ( group . mMeta . mVisibleMsgCount ) ) ;
if ( group . mMeta . mLastPost = = 0 )
ui - > infoLastPost - > setText ( tr ( " Never " ) ) ;
else
ui - > infoLastPost - > setText ( DateTime : : formatLongDateTime ( group . mMeta . mLastPost ) ) ;
2018-12-25 19:14:48 +01:00
QString formatDescription = QString : : fromUtf8 ( group . mDescription . c_str ( ) ) ;
unsigned int formatFlag = RSHTML_FORMATTEXT_EMBED_LINKS ;
// embed smileys ?
if ( Settings - > valueFromGroup ( QString ( " ChannelPostsWidget " ) , QString : : fromUtf8 ( " Emoteicons_ChannelDecription " ) , true ) . toBool ( ) ) {
formatFlag | = RSHTML_FORMATTEXT_EMBED_SMILEYS ;
}
formatDescription = RsHtml ( ) . formatText ( NULL , formatDescription , formatFlag ) ;
ui - > infoDescription - > setText ( formatDescription ) ;
2016-04-11 22:42:02 -04:00
ui - > infoAdministrator - > setId ( group . mMeta . mAuthorId ) ;
2018-12-25 19:14:48 +01:00
link = RetroShareLink : : createMessage ( group . mMeta . mAuthorId , " " ) ;
ui - > infoAdministrator - > setText ( link . toHtml ( ) ) ;
2016-04-11 22:42:02 -04:00
QString distrib_string ( " [unknown] " ) ;
switch ( group . mMeta . mCircleType )
{
case GXS_CIRCLE_TYPE_PUBLIC : distrib_string = tr ( " Public " ) ;
break ;
case GXS_CIRCLE_TYPE_EXTERNAL :
{
RsGxsCircleDetails det ;
// !! What we need here is some sort of CircleLabel, which loads the circle and updates the label when done.
if ( rsGxsCircles - > getCircleDetails ( group . mMeta . mCircleId , det ) )
distrib_string = tr ( " Restricted to members of circle \" " ) + QString : : fromUtf8 ( det . mCircleName . c_str ( ) ) + " \" " ;
else
distrib_string = tr ( " Restricted to members of circle " ) + QString : : fromStdString ( group . mMeta . mCircleId . toStdString ( ) ) ;
}
break ;
2016-05-06 21:37:17 -04:00
case GXS_CIRCLE_TYPE_YOUR_EYES_ONLY : distrib_string = tr ( " Your eyes only " ) ;
2016-04-11 22:42:02 -04:00
break ;
case GXS_CIRCLE_TYPE_LOCAL : distrib_string = tr ( " You and your friend nodes " ) ;
break ;
default :
std : : cerr < < " (EE) badly initialised group distribution ID = " < < group . mMeta . mCircleType < < std : : endl ;
}
ui - > infoDistribution - > setText ( distrib_string ) ;
2015-02-09 22:11:19 +00:00
ui - > infoWidget - > show ( ) ;
ui - > feedWidget - > hide ( ) ;
ui - > fileWidget - > hide ( ) ;
ui - > feedToolButton - > setEnabled ( false ) ;
ui - > fileToolButton - > setEnabled ( false ) ;
}
}
int GxsChannelPostsWidget : : viewMode ( )
{
if ( ui - > feedToolButton - > isChecked ( ) ) {
return VIEW_MODE_FEEDS ;
} else if ( ui - > fileToolButton - > isChecked ( ) ) {
return VIEW_MODE_FILES ;
}
/* Default */
return VIEW_MODE_FEEDS ;
2014-05-04 22:59:06 +00:00
}
2014-08-05 20:50:55 +00:00
void GxsChannelPostsWidget : : setViewMode ( int viewMode )
2014-05-27 06:57:45 +00:00
{
2014-08-05 20:50:55 +00:00
switch ( viewMode ) {
case VIEW_MODE_FEEDS :
ui - > feedWidget - > show ( ) ;
ui - > fileWidget - > hide ( ) ;
ui - > feedToolButton - > setChecked ( true ) ;
ui - > fileToolButton - > setChecked ( false ) ;
2014-08-01 14:49:58 +00:00
2014-08-05 20:50:55 +00:00
break ;
case VIEW_MODE_FILES :
ui - > feedWidget - > hide ( ) ;
ui - > fileWidget - > show ( ) ;
ui - > feedToolButton - > setChecked ( false ) ;
ui - > fileToolButton - > setChecked ( true ) ;
break ;
default :
setViewMode ( VIEW_MODE_FEEDS ) ;
2014-05-27 06:57:45 +00:00
return ;
}
2014-08-05 20:50:55 +00:00
}
void GxsChannelPostsWidget : : filterChanged ( int filter )
{
ui - > feedWidget - > setFilterType ( filter ) ;
ui - > fileWidget - > setFilterType ( filter ) ;
2014-05-27 06:57:45 +00:00
}
2014-08-01 14:49:58 +00:00
/*static*/ bool GxsChannelPostsWidget : : filterItem ( FeedItem * feedItem , const QString & text , int filter )
2014-05-27 06:57:45 +00:00
{
2014-08-01 14:49:58 +00:00
GxsChannelPostItem * item = dynamic_cast < GxsChannelPostItem * > ( feedItem ) ;
if ( ! item ) {
return true ;
2014-05-27 06:57:45 +00:00
}
bool bVisible = text . isEmpty ( ) ;
2016-02-08 19:42:56 +01:00
if ( ! bVisible )
2014-05-27 06:57:45 +00:00
{
2016-02-08 19:42:56 +01:00
switch ( filter )
2014-05-27 06:57:45 +00:00
{
2016-02-08 19:42:56 +01:00
case FILTER_TITLE :
bVisible = item - > getTitleLabel ( ) . contains ( text , Qt : : CaseInsensitive ) ;
break ;
case FILTER_MSG :
bVisible = item - > getMsgLabel ( ) . contains ( text , Qt : : CaseInsensitive ) ;
break ;
case FILTER_FILE_NAME :
{
std : : list < SubFileItem * > fileItems = item - > getFileItems ( ) ;
std : : list < SubFileItem * > : : iterator lit ;
for ( lit = fileItems . begin ( ) ; lit ! = fileItems . end ( ) ; + + lit )
{
SubFileItem * fi = * lit ;
QString fileName = QString : : fromUtf8 ( fi - > FileName ( ) . c_str ( ) ) ;
bVisible = ( bVisible | | fileName . contains ( text , Qt : : CaseInsensitive ) ) ;
}
break ;
}
default :
bVisible = true ;
break ;
2014-05-27 06:57:45 +00:00
}
}
2014-08-01 14:49:58 +00:00
return bVisible ;
2014-07-23 18:51:56 +00:00
}
2017-07-16 16:56:23 +02:00
void GxsChannelPostsWidget : : createPostItem ( const RsGxsChannelPost & post , bool related )
2014-08-01 18:54:55 +00:00
{
GxsChannelPostItem * item = NULL ;
2017-05-15 22:13:36 +02:00
if ( ! post . mMeta . mOrigMsgId . isNull ( ) )
{
FeedItem * feedItem = ui - > feedWidget - > findGxsFeedItem ( post . mMeta . mGroupId , post . mMeta . mOrigMsgId ) ;
item = dynamic_cast < GxsChannelPostItem * > ( feedItem ) ;
if ( item )
{
ui - > feedWidget - > removeFeedItem ( item ) ;
2017-07-03 23:21:31 +02:00
2017-07-16 16:56:23 +02:00
GxsChannelPostItem * item = new GxsChannelPostItem ( this , 0 , post , true , false , post . mOlderVersions ) ;
2017-05-15 22:13:36 +02:00
ui - > feedWidget - > addFeedItem ( item , ROLE_PUBLISH , QDateTime : : fromTime_t ( post . mMeta . mPublishTs ) ) ;
return ;
}
}
if ( related )
{
2014-08-01 18:54:55 +00:00
FeedItem * feedItem = ui - > feedWidget - > findGxsFeedItem ( post . mMeta . mGroupId , post . mMeta . mMsgId ) ;
item = dynamic_cast < GxsChannelPostItem * > ( feedItem ) ;
}
if ( item ) {
2014-11-18 00:49:21 +00:00
item - > setPost ( post ) ;
2014-08-01 18:54:55 +00:00
ui - > feedWidget - > setSort ( item , ROLE_PUBLISH , QDateTime : : fromTime_t ( post . mMeta . mPublishTs ) ) ;
} else {
2017-07-16 16:56:23 +02:00
GxsChannelPostItem * item = new GxsChannelPostItem ( this , 0 , post , true , false , post . mOlderVersions ) ;
2014-08-01 18:54:55 +00:00
ui - > feedWidget - > addFeedItem ( item , ROLE_PUBLISH , QDateTime : : fromTime_t ( post . mMeta . mPublishTs ) ) ;
}
2014-08-05 20:50:55 +00:00
ui - > fileWidget - > addFiles ( post , related ) ;
2014-08-01 18:54:55 +00:00
}
void GxsChannelPostsWidget : : fillThreadCreatePost ( const QVariant & post , bool related , int current , int count )
{
/* show fill progress */
if ( count ) {
ui - > progressBar - > setValue ( current * ui - > progressBar - > maximum ( ) / count ) ;
}
if ( ! post . canConvert < RsGxsChannelPost > ( ) ) {
return ;
}
createPostItem ( post . value < RsGxsChannelPost > ( ) , related ) ;
}
void GxsChannelPostsWidget : : insertChannelPosts ( std : : vector < RsGxsChannelPost > & posts , GxsMessageFramePostThread * thread , bool related )
2014-05-04 22:59:06 +00:00
{
2014-08-01 18:54:55 +00:00
if ( related & & thread ) {
std : : cerr < < " GxsChannelPostsWidget::insertChannelPosts fill only related posts as thread is not possible " < < std : : endl ;
return ;
}
int count = posts . size ( ) ;
int pos = 0 ;
2014-05-04 22:59:06 +00:00
2014-08-01 18:54:55 +00:00
if ( ! thread ) {
ui - > feedWidget - > setSortingEnabled ( false ) ;
}
2014-08-01 14:49:58 +00:00
2017-05-12 23:54:02 +02:00
// collect new versions of posts if any
2017-05-13 20:41:56 +02:00
# ifdef DEBUG_CHANNEL
2017-05-12 23:54:02 +02:00
std : : cerr < < " Inserting channel posts " < < std : : endl ;
2017-05-13 20:41:56 +02:00
# endif
2017-05-12 23:54:02 +02:00
std : : vector < uint32_t > new_versions ;
for ( uint32_t i = 0 ; i < posts . size ( ) ; + + i )
2017-05-13 17:13:05 +02:00
{
if ( posts [ i ] . mMeta . mOrigMsgId = = posts [ i ] . mMeta . mMsgId )
posts [ i ] . mMeta . mOrigMsgId . clear ( ) ;
2017-05-13 20:41:56 +02:00
# ifdef DEBUG_CHANNEL
2017-05-13 17:13:05 +02:00
std : : cerr < < " " < < i < < " : msg_id= " < < posts [ i ] . mMeta . mMsgId < < " : orig msg id = " < < posts [ i ] . mMeta . mOrigMsgId < < std : : endl ;
2017-05-13 20:41:56 +02:00
# endif
2017-05-13 17:13:05 +02:00
2017-05-12 23:54:02 +02:00
if ( ! posts [ i ] . mMeta . mOrigMsgId . isNull ( ) )
new_versions . push_back ( i ) ;
2017-05-13 17:13:05 +02:00
}
2017-05-12 23:54:02 +02:00
2017-05-13 20:41:56 +02:00
# ifdef DEBUG_CHANNEL
2017-05-12 23:54:02 +02:00
std : : cerr < < " New versions: " < < new_versions . size ( ) < < std : : endl ;
2017-05-13 20:41:56 +02:00
# endif
2017-05-12 23:54:02 +02:00
if ( ! new_versions . empty ( ) )
{
2017-05-13 20:41:56 +02:00
# ifdef DEBUG_CHANNEL
2017-05-12 23:54:02 +02:00
std : : cerr < < " New versions present. Replacing them... " < < std : : endl ;
2017-05-13 17:13:05 +02:00
std : : cerr < < " Creating search map. " < < std : : endl ;
2017-05-13 20:41:56 +02:00
# endif
2017-05-12 23:54:02 +02:00
// make a quick search map
std : : map < RsGxsMessageId , uint32_t > search_map ;
for ( uint32_t i = 0 ; i < posts . size ( ) ; + + i )
search_map [ posts [ i ] . mMeta . mMsgId ] = i ;
for ( uint32_t i = 0 ; i < new_versions . size ( ) ; + + i )
{
2017-05-13 20:41:56 +02:00
# ifdef DEBUG_CHANNEL
2017-05-13 17:13:05 +02:00
std : : cerr < < " Taking care of new version at index " < < new_versions [ i ] < < std : : endl ;
2017-05-13 20:41:56 +02:00
# endif
2017-05-13 17:13:05 +02:00
2017-05-12 23:54:02 +02:00
uint32_t current_index = new_versions [ i ] ;
uint32_t source_index = new_versions [ i ] ;
2017-07-15 13:24:07 +02:00
# ifdef DEBUG_CHANNEL
2017-05-13 17:13:05 +02:00
RsGxsMessageId source_msg_id = posts [ source_index ] . mMeta . mMsgId ;
2017-07-15 13:24:07 +02:00
# endif
2017-05-12 23:54:02 +02:00
2017-05-13 17:13:05 +02:00
// What we do is everytime we find a replacement post, we climb up the replacement graph until we find the original post
// (or the most recent version of it). When we reach this post, we replace it with the data of the source post.
// In the mean time, all other posts have their MsgId cleared, so that the posts are removed from the list.
2017-05-12 23:54:02 +02:00
2017-07-15 13:24:07 +02:00
//std::vector<uint32_t> versions ;
2017-05-13 17:13:05 +02:00
std : : map < RsGxsMessageId , uint32_t > : : const_iterator vit ;
while ( search_map . end ( ) ! = ( vit = search_map . find ( posts [ current_index ] . mMeta . mOrigMsgId ) ) )
2017-05-12 23:54:02 +02:00
{
2017-05-13 20:41:56 +02:00
# ifdef DEBUG_CHANNEL
2017-05-13 17:13:05 +02:00
std : : cerr < < " post at index " < < current_index < < " replaces a post at position " < < vit - > second ;
2017-05-13 20:41:56 +02:00
# endif
2014-08-01 18:54:55 +00:00
2017-05-13 17:13:05 +02:00
// Now replace the post only if the new versionis more recent. It may happen indeed that the same post has been corrected multiple
// times. In this case, we only need to replace the post with the newest version
2017-05-12 23:54:02 +02:00
2017-07-15 13:24:07 +02:00
//uint32_t prev_index = current_index ;
2017-05-13 17:13:05 +02:00
current_index = vit - > second ;
2017-05-12 23:54:02 +02:00
2017-05-13 17:13:05 +02:00
if ( posts [ current_index ] . mMeta . mMsgId . isNull ( ) ) // This handles the branching situation where this post has been already erased. No need to go down further.
{
2017-05-13 20:41:56 +02:00
# ifdef DEBUG_CHANNEL
2017-05-13 17:13:05 +02:00
std : : cerr < < " already erased. Stopping. " < < std : : endl ;
2017-05-13 20:41:56 +02:00
# endif
2017-05-13 17:13:05 +02:00
break ;
}
2017-05-12 23:54:02 +02:00
2017-05-13 17:13:05 +02:00
if ( posts [ current_index ] . mMeta . mPublishTs < posts [ source_index ] . mMeta . mPublishTs )
{
2017-05-13 20:41:56 +02:00
# ifdef DEBUG_CHANNEL
2017-05-13 17:13:05 +02:00
std : : cerr < < " and is more recent => following " < < std : : endl ;
2017-05-13 20:41:56 +02:00
# endif
2017-05-20 17:33:05 +02:00
for ( std : : set < RsGxsMessageId > : : const_iterator itt ( posts [ current_index ] . mOlderVersions . begin ( ) ) ; itt ! = posts [ current_index ] . mOlderVersions . end ( ) ; + + itt )
posts [ source_index ] . mOlderVersions . insert ( * itt ) ;
posts [ source_index ] . mOlderVersions . insert ( posts [ current_index ] . mMeta . mMsgId ) ;
2017-05-13 17:13:05 +02:00
posts [ current_index ] . mMeta . mMsgId . clear ( ) ; // clear the msg Id so the post will be ignored
}
2017-05-13 20:41:56 +02:00
# ifdef DEBUG_CHANNEL
2017-05-13 17:13:05 +02:00
else
std : : cerr < < " but is older -> Stopping " < < std : : endl ;
2017-05-13 20:41:56 +02:00
# endif
2017-05-13 17:13:05 +02:00
}
2017-05-12 23:54:02 +02:00
}
}
2017-05-13 20:41:56 +02:00
# ifdef DEBUG_CHANNEL
2017-05-13 17:13:05 +02:00
std : : cerr < < " Now adding posts... " < < std : : endl ;
2017-05-13 20:41:56 +02:00
# endif
2017-05-13 17:13:05 +02:00
2017-05-12 23:54:02 +02:00
for ( std : : vector < RsGxsChannelPost > : : const_reverse_iterator it = posts . rbegin ( ) ; it ! = posts . rend ( ) ; + + it )
2017-05-13 17:13:05 +02:00
{
2017-05-13 20:41:56 +02:00
# ifdef DEBUG_CHANNEL
2017-05-13 17:13:05 +02:00
std : : cerr < < " adding post: " < < ( * it ) . mMeta . mMsgId ;
2017-05-13 20:41:56 +02:00
# endif
2017-05-13 17:13:05 +02:00
if ( ! ( * it ) . mMeta . mMsgId . isNull ( ) )
2017-05-12 23:54:02 +02:00
{
2017-05-13 20:41:56 +02:00
# ifdef DEBUG_CHANNEL
2017-05-13 17:13:05 +02:00
std : : cerr < < " added " < < std : : endl ;
2017-05-13 20:41:56 +02:00
# endif
2017-05-13 17:13:05 +02:00
2017-05-12 23:54:02 +02:00
if ( thread & & thread - > stopped ( ) )
break ;
if ( thread )
thread - > emitAddPost ( qVariantFromValue ( * it ) , related , + + pos , count ) ;
else
createPostItem ( * it , related ) ;
2014-05-05 21:53:47 +00:00
}
2017-05-13 20:41:56 +02:00
# ifdef DEBUG_CHANNEL
2017-05-13 17:13:05 +02:00
else
std : : cerr < < " skipped " < < std : : endl ;
2017-05-13 20:41:56 +02:00
# endif
2017-05-13 17:13:05 +02:00
}
2014-08-01 14:49:58 +00:00
2014-08-01 18:54:55 +00:00
if ( ! thread ) {
ui - > feedWidget - > setSortingEnabled ( true ) ;
}
2014-08-01 14:49:58 +00:00
}
void GxsChannelPostsWidget : : clearPosts ( )
{
ui - > feedWidget - > clear ( ) ;
2014-08-06 15:02:22 +00:00
ui - > fileWidget - > clear ( ) ;
2014-05-04 22:59:06 +00:00
}
2018-06-25 23:08:10 +02:00
void GxsChannelPostsWidget : : blank ( )
{
mStateHelper - > setWidgetEnabled ( ui - > postButton , false ) ;
mStateHelper - > setWidgetEnabled ( ui - > subscribeToolButton , false ) ;
2019-01-13 18:12:30 +01:00
ui - > subscribersLabel - > setText ( " " ) ;
2018-06-25 23:08:10 +02:00
clearPosts ( ) ;
groupNameChanged ( QString ( ) ) ;
ui - > infoWidget - > hide ( ) ;
ui - > feedWidget - > show ( ) ;
ui - > fileWidget - > hide ( ) ;
}
2014-10-25 23:52:33 +00:00
bool GxsChannelPostsWidget : : navigatePostItem ( const RsGxsMessageId & msgId )
{
FeedItem * feedItem = ui - > feedWidget - > findGxsFeedItem ( groupId ( ) , msgId ) ;
if ( ! feedItem ) {
return false ;
}
return ui - > feedWidget - > scrollTo ( feedItem , true ) ;
}
2014-07-05 18:33:11 +00:00
void GxsChannelPostsWidget : : subscribeGroup ( bool subscribe )
2014-05-04 22:59:06 +00:00
{
2018-11-01 07:04:01 +01:00
RsGxsGroupId grpId ( groupId ( ) ) ;
if ( grpId . isNull ( ) ) return ;
2014-07-05 18:33:11 +00:00
2018-11-01 07:04:01 +01:00
RsThread : : async ( [ = ] ( )
{
rsGxsChannels - > subscribeToChannel ( grpId , subscribe ) ;
} ) ;
2014-07-05 18:33:11 +00:00
}
void GxsChannelPostsWidget : : setAutoDownload ( bool autoDl )
{
mAutoDownloadAction - > setChecked ( autoDl ) ;
mAutoDownloadAction - > setText ( autoDl ? tr ( " Disable Auto-Download " ) : tr ( " Enable Auto-Download " ) ) ;
}
void GxsChannelPostsWidget : : toggleAutoDownload ( )
{
RsGxsGroupId grpId = groupId ( ) ;
if ( grpId . isNull ( ) ) {
return ;
}
2018-11-01 07:04:01 +01:00
bool autoDownload ;
if ( ! rsGxsChannels - > getChannelAutoDownload ( grpId , autoDownload ) )
2014-07-05 18:33:11 +00:00
{
2018-11-01 07:04:01 +01:00
std : : cerr < < __PRETTY_FUNCTION__ < < " failed to get autodownload value "
< < " for channel: " < < grpId . toStdString ( ) < < std : : endl ;
return ;
2014-05-04 22:59:06 +00:00
}
2018-11-01 07:04:01 +01:00
RsThread : : async ( [ this , grpId , autoDownload ] ( )
{
if ( ! rsGxsChannels - > setChannelAutoDownload ( grpId , ! autoDownload ) )
{
std : : cerr < < __PRETTY_FUNCTION__ < < " failed to set autodownload "
< < " for channel: " < < grpId . toStdString ( ) < < std : : endl ;
return ;
}
2018-11-01 14:51:57 +01:00
RsQThreadUtils : : postToObject ( [ = ] ( )
2018-11-01 07:04:01 +01:00
{
/* Here it goes any code you want to be executed on the Qt Gui
* thread , for example to update the data model with new information
* after a blocking call to RetroShare API complete , note that
* Qt : : QueuedConnection is important !
*/
2018-11-01 14:51:57 +01:00
std : : cerr < < __PRETTY_FUNCTION__ < < " Has been executed on GUI "
< < " thread but was scheduled by async thread " < < std : : endl ;
} , this ) ;
2018-11-01 07:04:01 +01:00
} ) ;
2014-05-04 22:59:06 +00:00
}
2014-07-23 18:51:56 +00:00
bool GxsChannelPostsWidget : : insertGroupData ( const uint32_t & token , RsGroupMetaData & metaData )
2014-05-05 21:53:47 +00:00
{
2014-05-04 22:59:06 +00:00
std : : vector < RsGxsChannelGroup > groups ;
rsGxsChannels - > getGroupData ( token , groups ) ;
2018-06-26 22:20:02 +02:00
if ( groups . size ( ) = = 1 )
2014-05-04 22:59:06 +00:00
{
insertChannelDetails ( groups [ 0 ] ) ;
2014-07-23 18:51:56 +00:00
metaData = groups [ 0 ] . mMeta ;
return true ;
2014-05-04 22:59:06 +00:00
}
2018-06-26 22:20:02 +02:00
else
{
RsGxsChannelGroup distant_group ;
if ( rsGxsChannels - > retrieveDistantGroup ( groupId ( ) , distant_group ) )
{
insertChannelDetails ( distant_group ) ;
metaData = distant_group . mMeta ;
return true ;
}
}
2014-05-04 22:59:06 +00:00
2014-07-23 18:51:56 +00:00
return false ;
2014-05-04 22:59:06 +00:00
}
2015-08-13 15:22:48 +02:00
void GxsChannelPostsWidget : : insertAllPosts ( const uint32_t & token , GxsMessageFramePostThread * thread )
2014-05-04 22:59:06 +00:00
{
std : : vector < RsGxsChannelPost > posts ;
rsGxsChannels - > getPostData ( token , posts ) ;
2014-08-01 18:54:55 +00:00
insertChannelPosts ( posts , thread , false ) ;
2014-05-05 21:53:47 +00:00
}
2015-08-13 15:22:48 +02:00
void GxsChannelPostsWidget : : insertPosts ( const uint32_t & token )
2014-05-05 21:53:47 +00:00
{
std : : vector < RsGxsChannelPost > posts ;
2015-08-13 15:22:48 +02:00
rsGxsChannels - > getPostData ( token , posts ) ;
2014-05-05 21:53:47 +00:00
2014-08-01 18:54:55 +00:00
insertChannelPosts ( posts , NULL , true ) ;
2014-05-04 22:59:06 +00:00
}
2015-03-14 21:13:28 +00:00
class GxsChannelPostsReadData
2014-05-04 22:59:06 +00:00
{
2015-03-14 21:13:28 +00:00
public :
GxsChannelPostsReadData ( bool read )
{
mRead = read ;
mLastToken = 0 ;
}
2014-08-01 14:49:58 +00:00
2015-03-14 21:13:28 +00:00
public :
bool mRead ;
uint32_t mLastToken ;
} ;
2014-05-04 22:59:06 +00:00
2015-03-14 21:13:28 +00:00
static void setAllMessagesReadCallback ( FeedItem * feedItem , void * data )
{
GxsChannelPostItem * channelPostItem = dynamic_cast < GxsChannelPostItem * > ( feedItem ) ;
if ( ! channelPostItem ) {
return ;
}
2015-02-22 10:10:34 +00:00
2015-03-14 21:13:28 +00:00
GxsChannelPostsReadData * readData = ( GxsChannelPostsReadData * ) data ;
bool is_not_new = ! channelPostItem - > isUnread ( ) ;
2015-02-22 10:10:34 +00:00
2015-03-14 21:13:28 +00:00
if ( is_not_new = = readData - > mRead )
return ;
RsGxsGrpMsgIdPair msgPair = std : : make_pair ( channelPostItem - > groupId ( ) , channelPostItem - > messageId ( ) ) ;
rsGxsChannels - > setMessageReadStatus ( readData - > mLastToken , msgPair , readData - > mRead ) ;
2014-08-01 14:49:58 +00:00
}
2015-03-14 21:13:28 +00:00
void GxsChannelPostsWidget : : setAllMessagesReadDo ( bool read , uint32_t & token )
2014-08-01 14:49:58 +00:00
{
if ( groupId ( ) . isNull ( ) | | ! IS_GROUP_SUBSCRIBED ( subscribeFlags ( ) ) ) {
return ;
}
2015-03-14 21:13:28 +00:00
GxsChannelPostsReadData data ( read ) ;
ui - > feedWidget - > withAll ( setAllMessagesReadCallback , & data ) ;
token = data . mLastToken ;
2014-05-04 22:59:06 +00:00
}