2019-06-25 17:08:31 -04:00
/*******************************************************************************
2019-06-28 05:12:44 -04:00
* retroshare - gui / src / gui / msgs / RsFriendListModel . cpp *
2019-06-25 17:08:31 -04:00
* *
* Copyright 2019 by Cyril Soler < csoler @ users . sourceforge . net > *
* *
* 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 <list>
# include <QApplication>
# include <QDateTime>
# include <QFontMetrics>
# include <QModelIndex>
# include <QIcon>
2019-06-28 05:12:44 -04:00
# include "gui/common/StatusDefs.h"
2019-08-12 07:43:45 -04:00
# include "gui/common/AvatarDefs.h"
2019-06-25 17:08:31 -04:00
# include "util/HandleRichText.h"
# include "util/DateTime.h"
2019-06-28 05:12:44 -04:00
# include "gui/common/FriendListModel.h"
2019-06-25 17:08:31 -04:00
# include "gui/gxs/GxsIdDetails.h"
# include "gui/gxs/GxsIdTreeWidgetItem.h"
# include "retroshare/rsexpr.h"
# include "retroshare/rsmsgs.h"
//#define DEBUG_MESSAGE_MODEL
# define IS_MESSAGE_UNREAD(flags) (flags & (RS_MSG_NEW | RS_MSG_UNREAD_BY_USER))
# define IMAGE_STAR_ON ": / images / star-on-16.png"
# define IMAGE_STAR_OFF ": / images / star-off-16.png"
std : : ostream & operator < < ( std : : ostream & o , const QModelIndex & i ) ; // defined elsewhere
2019-06-28 05:12:44 -04:00
const QString RsFriendListModel : : FilterString ( " filtered " ) ;
2019-08-21 16:39:07 -04:00
const uint32_t MAX_INTERNAL_DATA_UPDATE_DELAY = 300 ; // re-update the internal data every 5 mins. Should properly cover sleep/wake-up changes.
const uint32_t MAX_NODE_UPDATE_DELAY = 1 ; // re-update the internal data every 5 mins. Should properly cover sleep/wake-up changes.
2019-06-25 17:08:31 -04:00
2019-08-03 17:22:48 -04:00
static const uint32_t NODE_DETAILS_UPDATE_DELAY = 5 ; // update each node every 5 secs.
2019-06-28 05:12:44 -04:00
RsFriendListModel : : RsFriendListModel ( QObject * parent )
2019-06-25 17:08:31 -04:00
: QAbstractItemModel ( parent )
{
2019-07-27 17:42:39 -04:00
mDisplayGroups = true ;
2019-06-25 17:08:31 -04:00
mFilterStrings . clear ( ) ;
2019-08-21 16:39:07 -04:00
mLastNodeUpdate = 0 ;
mLastInternalDataUpdate = 0 ;
2019-06-25 17:08:31 -04:00
}
2019-08-15 13:43:41 -04:00
void RsFriendListModel : : setDisplayStatusString ( bool b )
{
mDisplayStatusString = b ;
postMods ( ) ;
}
2019-06-28 10:20:26 -04:00
void RsFriendListModel : : setDisplayGroups ( bool b )
{
mDisplayGroups = b ;
2019-08-01 10:53:59 -04:00
updateInternalData ( ) ;
2019-06-28 10:20:26 -04:00
}
2019-06-28 05:12:44 -04:00
void RsFriendListModel : : preMods ( )
2019-06-25 17:08:31 -04:00
{
emit layoutAboutToBeChanged ( ) ;
}
2019-06-28 05:12:44 -04:00
void RsFriendListModel : : postMods ( )
2019-06-25 17:08:31 -04:00
{
2019-08-01 10:53:59 -04:00
emit dataChanged ( createIndex ( 0 , 0 , ( void * ) NULL ) , createIndex ( mTopLevel . size ( ) - 1 , COLUMN_THREAD_NB_COLUMNS - 1 , ( void * ) NULL ) ) ;
2019-06-25 17:08:31 -04:00
}
2019-06-28 05:12:44 -04:00
int RsFriendListModel : : rowCount ( const QModelIndex & parent ) const
2019-06-25 17:08:31 -04:00
{
2019-06-28 18:14:27 -04:00
if ( parent . column ( ) > = COLUMN_THREAD_NB_COLUMNS )
2019-06-25 17:08:31 -04:00
return 0 ;
2019-06-28 18:14:27 -04:00
if ( parent . internalId ( ) = = 0 )
2019-08-01 10:53:59 -04:00
return mTopLevel . size ( ) ;
2019-06-28 18:14:27 -04:00
EntryIndex index ;
if ( ! convertInternalIdToIndex ( parent . internalId ( ) , index ) )
return 0 ;
if ( index . type = = ENTRY_TYPE_GROUP )
2019-08-01 10:53:59 -04:00
return mGroups [ index . group_index ] . child_profile_indices . size ( ) ;
2019-06-29 17:55:38 -04:00
if ( index . type = = ENTRY_TYPE_PROFILE )
2019-08-01 10:53:59 -04:00
if ( index . group_index < 0xff )
return mProfiles [ mGroups [ index . group_index ] . child_profile_indices [ index . profile_index ] ] . child_node_indices . size ( ) ;
else
return mProfiles [ index . profile_index ] . child_node_indices . size ( ) ;
2019-06-25 17:08:31 -04:00
2019-08-01 10:53:59 -04:00
if ( index . type = = ENTRY_TYPE_NODE )
return 0 ;
2019-06-25 17:08:31 -04:00
}
2019-06-28 05:12:44 -04:00
int RsFriendListModel : : columnCount ( const QModelIndex & parent ) const
2019-06-25 17:08:31 -04:00
{
return COLUMN_THREAD_NB_COLUMNS ;
}
2019-06-28 05:12:44 -04:00
// bool RsFriendListModel::getProfileData(const QModelIndex& i,Rs::Msgs::MessageInfo& fmpe) const
// {
// if(!i.isValid())
// return true;
//
// quintptr ref = i.internalId();
// uint32_t index = 0;
//
// if(!convertInternalIdToMsgIndex(ref,index) || index >= mMessages.size())
// return false ;
//
// return rsMsgs->getMessage(mMessages[index].msgId,fmpe);
// }
2019-06-25 17:08:31 -04:00
2019-06-28 05:12:44 -04:00
bool RsFriendListModel : : hasChildren ( const QModelIndex & parent ) const
2019-06-25 17:08:31 -04:00
{
if ( ! parent . isValid ( ) )
return true ;
2019-06-28 18:14:27 -04:00
EntryIndex parent_index ;
convertInternalIdToIndex ( parent . internalId ( ) , parent_index ) ;
if ( parent_index . type = = ENTRY_TYPE_NODE )
return false ;
2019-08-01 10:53:59 -04:00
2019-06-28 18:14:27 -04:00
if ( parent_index . type = = ENTRY_TYPE_PROFILE )
2019-08-01 10:53:59 -04:00
if ( parent_index . group_index < 0xff )
return ! mProfiles [ mGroups [ parent_index . group_index ] . child_profile_indices [ parent_index . profile_index ] ] . child_node_indices . empty ( ) ;
else
return ! mProfiles [ parent_index . profile_index ] . child_node_indices . empty ( ) ;
2019-06-28 18:14:27 -04:00
if ( parent_index . type = = ENTRY_TYPE_GROUP )
2019-08-01 10:53:59 -04:00
return ! mGroups [ parent_index . group_index ] . child_profile_indices . empty ( ) ;
2019-06-28 18:14:27 -04:00
return false ;
2019-06-25 17:08:31 -04:00
}
2019-08-01 10:53:59 -04:00
RsFriendListModel : : EntryIndex RsFriendListModel : : EntryIndex : : parent ( ) const
{
EntryIndex i ( * this ) ;
switch ( type )
{
2019-08-02 09:40:11 -04:00
case ENTRY_TYPE_GROUP : return EntryIndex ( ) ;
2019-08-01 10:53:59 -04:00
2019-08-02 09:40:11 -04:00
case ENTRY_TYPE_PROFILE :
if ( i . group_index = = 0xff )
return EntryIndex ( ) ;
else
2019-08-11 05:46:49 -04:00
{
2019-08-02 09:40:11 -04:00
i . type = ENTRY_TYPE_GROUP ;
2019-08-11 05:46:49 -04:00
i . profile_index = 0xff ;
}
2019-08-01 10:53:59 -04:00
break ;
case ENTRY_TYPE_NODE : i . type = ENTRY_TYPE_PROFILE ;
2019-08-11 05:46:49 -04:00
i . node_index = 0xff ;
2019-08-01 10:53:59 -04:00
break ;
}
return i ;
}
2019-08-01 17:55:42 -04:00
RsFriendListModel : : EntryIndex RsFriendListModel : : EntryIndex : : child ( int row , const std : : vector < EntryIndex > & top_level ) const
2019-08-01 10:53:59 -04:00
{
EntryIndex i ( * this ) ;
switch ( type )
{
2019-08-02 09:40:11 -04:00
case ENTRY_TYPE_UNKNOWN :
i = top_level [ row ] ;
2019-08-01 10:53:59 -04:00
break ;
case ENTRY_TYPE_GROUP : i . type = ENTRY_TYPE_PROFILE ;
2019-08-01 17:55:42 -04:00
i . profile_index = row ;
2019-08-01 10:53:59 -04:00
break ;
2019-08-01 17:55:42 -04:00
case ENTRY_TYPE_PROFILE : i . type = ENTRY_TYPE_NODE ;
i . node_index = row ;
2019-08-01 10:53:59 -04:00
break ;
2019-08-01 17:55:42 -04:00
case ENTRY_TYPE_NODE : i = EntryIndex ( ) ;
2019-08-01 10:53:59 -04:00
break ;
}
return i ;
}
uint32_t RsFriendListModel : : EntryIndex : : parentRow ( uint32_t nb_groups ) const
{
switch ( type )
{
default :
2019-08-02 09:40:11 -04:00
case ENTRY_TYPE_UNKNOWN : return 0 ;
2019-08-01 10:53:59 -04:00
case ENTRY_TYPE_GROUP : return group_index ;
case ENTRY_TYPE_PROFILE : return ( group_index = = 0xff ) ? ( profile_index + nb_groups ) : profile_index ;
case ENTRY_TYPE_NODE : return node_index ;
}
}
// The index encodes the whole hierarchy of parents. This allows to very efficiently compute indices of the parent of an index.
//
// The format is the following:
//
// 0x 00 00 00 00
// | | | |
// | | | +---- location/node index
// | | +------- profile index
// | +---------- group index
2019-08-02 09:40:11 -04:00
// +------------- type
2019-08-01 10:53:59 -04:00
//
// Only valid indexes a 0x01->0xff. 0x00 means "no index"
//
2019-06-28 05:12:44 -04:00
bool RsFriendListModel : : convertIndexToInternalId ( const EntryIndex & e , quintptr & id )
2019-06-25 17:08:31 -04:00
{
// the internal id is set to the place in the table of items. We simply shift to allow 0 to mean something special.
2019-08-02 09:40:11 -04:00
id = ( ( ( uint32_t ) e . type ) < < 24 ) + ( ( uint32_t ) e . group_index < < 16 ) + ( uint32_t ) ( e . profile_index < < 8 ) + ( uint32_t ) e . node_index ;
2019-06-25 17:08:31 -04:00
return true ;
}
2019-06-28 05:12:44 -04:00
bool RsFriendListModel : : convertInternalIdToIndex ( quintptr ref , EntryIndex & e )
2019-06-25 17:08:31 -04:00
{
if ( ref = = 0 )
return false ;
2019-08-01 17:55:42 -04:00
e . group_index = ( ref > > 16 ) & 0xff ;
e . profile_index = ( ref > > 8 ) & 0xff ;
e . node_index = ( ref > > 0 ) & 0xff ;
2019-06-28 05:12:44 -04:00
2019-08-02 09:40:11 -04:00
e . type = static_cast < EntryType > ( ( ref > > 24 ) & 0xff ) ;
2019-06-28 05:12:44 -04:00
2019-06-25 17:08:31 -04:00
return true ;
}
2019-08-01 10:53:59 -04:00
QModelIndex RsFriendListModel : : index ( int row , int column , const QModelIndex & parent ) const
2019-06-25 17:08:31 -04:00
{
if ( row < 0 | | column < 0 | | column > = COLUMN_THREAD_NB_COLUMNS )
return QModelIndex ( ) ;
2019-06-28 05:12:44 -04:00
if ( parent . internalId ( ) = = 0 )
{
quintptr ref ;
2019-08-17 09:25:32 -04:00
convertIndexToInternalId ( mTopLevel [ row ] , ref ) ;
2019-06-25 17:08:31 -04:00
return createIndex ( row , column , ref ) ;
2019-06-28 05:12:44 -04:00
}
EntryIndex parent_index ;
convertInternalIdToIndex ( parent . internalId ( ) , parent_index ) ;
2019-08-15 09:49:20 -04:00
# ifdef DEBUG_MODEL
2019-07-28 03:12:55 -04:00
RsDbg ( ) < < " Index row= " < < row < < " col= " < < column < < " parent= " < < parent < < std : : endl ;
2019-08-15 09:49:20 -04:00
# endif
2019-07-28 03:12:55 -04:00
2019-08-01 10:53:59 -04:00
quintptr ref ;
2019-08-01 17:55:42 -04:00
EntryIndex new_index = parent_index . child ( row , mTopLevel ) ;
2019-06-28 05:12:44 -04:00
convertIndexToInternalId ( new_index , ref ) ;
2019-08-15 09:49:20 -04:00
# ifdef DEBUG_MODEL
2019-07-28 03:12:55 -04:00
RsDbg ( ) < < " returning " < < createIndex ( row , column , ref ) < < std : : endl ;
2019-08-15 09:49:20 -04:00
# endif
2019-07-28 03:12:55 -04:00
2019-06-28 05:12:44 -04:00
return createIndex ( row , column , ref ) ;
2019-06-25 17:08:31 -04:00
}
2019-06-28 05:12:44 -04:00
QModelIndex RsFriendListModel : : parent ( const QModelIndex & index ) const
2019-06-25 17:08:31 -04:00
{
if ( ! index . isValid ( ) )
return QModelIndex ( ) ;
2019-06-28 18:14:27 -04:00
EntryIndex I ;
convertInternalIdToIndex ( index . internalId ( ) , I ) ;
2019-08-01 10:53:59 -04:00
EntryIndex p = I . parent ( ) ;
2019-06-28 18:14:27 -04:00
2019-08-01 10:53:59 -04:00
if ( p . type = = ENTRY_TYPE_UNKNOWN )
return QModelIndex ( ) ;
2019-06-29 17:55:38 -04:00
2019-08-01 10:53:59 -04:00
quintptr i ;
convertIndexToInternalId ( p , i ) ;
2019-06-28 18:14:27 -04:00
2019-08-01 10:53:59 -04:00
return createIndex ( I . parentRow ( mGroups . size ( ) ) , 0 , i ) ;
2019-06-25 17:08:31 -04:00
}
2019-06-28 05:12:44 -04:00
Qt : : ItemFlags RsFriendListModel : : flags ( const QModelIndex & index ) const
2019-06-25 17:08:31 -04:00
{
if ( ! index . isValid ( ) )
return 0 ;
return QAbstractItemModel : : flags ( index ) ;
}
2019-06-28 05:12:44 -04:00
QVariant RsFriendListModel : : headerData ( int section , Qt : : Orientation orientation , int role ) const
2019-06-25 17:08:31 -04:00
{
if ( role = = Qt : : DisplayRole )
switch ( section )
{
2019-06-28 05:12:44 -04:00
case COLUMN_THREAD_NAME : return tr ( " Name " ) ;
case COLUMN_THREAD_ID : return tr ( " Id " ) ;
case COLUMN_THREAD_LAST_CONTACT : return tr ( " Last contact " ) ;
case COLUMN_THREAD_IP : return tr ( " IP " ) ;
2019-06-25 17:08:31 -04:00
default :
return QVariant ( ) ;
}
return QVariant ( ) ;
}
2019-06-28 05:12:44 -04:00
QVariant RsFriendListModel : : data ( const QModelIndex & index , int role ) const
2019-06-25 17:08:31 -04:00
{
# ifdef DEBUG_MESSAGE_MODEL
std : : cerr < < " calling data( " < < index < < " ) role= " < < role < < std : : endl ;
# endif
if ( ! index . isValid ( ) )
return QVariant ( ) ;
quintptr ref = ( index . isValid ( ) ) ? index . internalId ( ) : 0 ;
# ifdef DEBUG_MESSAGE_MODEL
std : : cerr < < " data( " < < index < < " ) " ;
# endif
if ( ! ref )
{
# ifdef DEBUG_MESSAGE_MODEL
std : : cerr < < " [empty] " < < std : : endl ;
# endif
return QVariant ( ) ;
}
2019-06-28 05:12:44 -04:00
EntryIndex entry ;
if ( ! convertInternalIdToIndex ( ref , entry ) )
2019-06-25 17:08:31 -04:00
{
# ifdef DEBUG_MESSAGE_MODEL
std : : cerr < < " Bad pointer: " < < ( void * ) ref < < std : : endl ;
# endif
return QVariant ( ) ;
}
switch ( role )
{
2019-08-12 07:43:45 -04:00
case Qt : : SizeHintRole : return sizeHintRole ( entry , index . column ( ) ) ;
2019-08-06 13:41:18 -04:00
case Qt : : DisplayRole : return displayRole ( entry , index . column ( ) ) ;
case Qt : : FontRole : return fontRole ( entry , index . column ( ) ) ;
case Qt : : TextColorRole : return textColorRole ( entry , index . column ( ) ) ;
2019-08-12 07:43:45 -04:00
case Qt : : DecorationRole : return decorationRole ( entry , index . column ( ) ) ;
2019-08-12 06:49:04 -04:00
2019-08-06 16:52:07 -04:00
case FilterRole : return filterRole ( entry , index . column ( ) ) ;
2019-08-12 05:20:53 -04:00
case SortRole : return sortRole ( entry , index . column ( ) ) ;
2019-08-12 06:49:04 -04:00
case OnlineRole : return onlineRole ( entry , index . column ( ) ) ;
2019-06-25 17:08:31 -04:00
default :
return QVariant ( ) ;
}
2019-06-28 05:12:44 -04:00
// case Qt::ToolTipRole: return toolTipRole (fmpe,index.column()) ;
// case Qt::UserRole: return userRole (fmpe,index.column()) ;
//
}
QVariant RsFriendListModel : : textColorRole ( const EntryIndex & fmpe , int column ) const
2019-06-25 17:08:31 -04:00
{
2019-08-06 13:41:18 -04:00
switch ( fmpe . type )
{
case ENTRY_TYPE_GROUP : return QVariant ( QBrush ( mTextColorGroup ) ) ;
2019-08-07 16:35:57 -04:00
case ENTRY_TYPE_PROFILE :
2019-08-12 06:49:04 -04:00
case ENTRY_TYPE_NODE : return QVariant ( QBrush ( mTextColorStatus [ onlineRole ( fmpe , column ) . toBool ( ) ? RS_STATUS_ONLINE : RS_STATUS_OFFLINE ] ) ) ;
2019-08-06 13:41:18 -04:00
default :
return QVariant ( ) ;
}
2019-06-25 17:08:31 -04:00
}
2019-06-28 05:12:44 -04:00
QVariant RsFriendListModel : : statusRole ( const EntryIndex & fmpe , int column ) const
2019-06-25 17:08:31 -04:00
{
// if(column != COLUMN_THREAD_DATA)
// return QVariant();
return QVariant ( ) ; //fmpe.mMsgStatus);
}
2019-06-28 05:12:44 -04:00
bool RsFriendListModel : : passesFilter ( const EntryIndex & e , int column ) const
{
2019-08-06 16:52:07 -04:00
QString s ;
bool passes_strings = true ;
2019-08-12 06:49:04 -04:00
if ( e . type = = ENTRY_TYPE_PROFILE & & ! mFilterStrings . empty ( ) )
2019-08-06 16:52:07 -04:00
{
switch ( mFilterType )
{
case FILTER_TYPE_ID : s = displayRole ( e , COLUMN_THREAD_ID ) . toString ( ) ;
break ;
case FILTER_TYPE_NAME : s = displayRole ( e , COLUMN_THREAD_NAME ) . toString ( ) ;
if ( s . isNull ( ) )
passes_strings = false ;
break ;
} ;
}
if ( ! s . isNull ( ) )
for ( auto iter ( mFilterStrings . begin ( ) ) ; iter ! = mFilterStrings . end ( ) ; + + iter )
passes_strings = passes_strings & & s . contains ( * iter , Qt : : CaseInsensitive ) ;
return passes_strings ;
2019-06-28 05:12:44 -04:00
}
QVariant RsFriendListModel : : filterRole ( const EntryIndex & e , int column ) const
{
if ( passesFilter ( e , column ) )
2019-06-25 17:08:31 -04:00
return QVariant ( FilterString ) ;
return QVariant ( QString ( ) ) ;
}
2019-06-28 05:12:44 -04:00
uint32_t RsFriendListModel : : updateFilterStatus ( ForumModelIndex i , int column , const QStringList & strings )
2019-06-25 17:08:31 -04:00
{
QString s ;
uint32_t count = 0 ;
return count ;
}
2019-06-28 05:12:44 -04:00
void RsFriendListModel : : setFilter ( FilterType filter_type , const QStringList & strings )
2019-06-25 17:08:31 -04:00
{
2019-08-15 09:49:20 -04:00
# ifdef DEBUG_MODEL
2019-06-25 17:08:31 -04:00
std : : cerr < < " Setting filter to filter_type= " < < int ( filter_type ) < < " and strings to " ;
foreach ( const QString & str , strings )
std : : cerr < < " \" " < < str . toStdString ( ) < < " \" " ;
std : : cerr < < std : : endl ;
2019-08-15 09:49:20 -04:00
# endif
2019-06-25 17:08:31 -04:00
preMods ( ) ;
mFilterType = filter_type ;
mFilterStrings = strings ;
postMods ( ) ;
}
2019-06-28 05:12:44 -04:00
QVariant RsFriendListModel : : toolTipRole ( const EntryIndex & fmpe , int column ) const
{
// if(column == COLUMN_THREAD_AUTHOR)
// {
// QString str,comment ;
// QList<QIcon> icons;
//
// if(!GxsIdDetails::MakeIdDesc(RsGxsId(fmpe.srcId.toStdString()), true, str, icons, comment,GxsIdDetails::ICON_TYPE_AVATAR))
// return QVariant();
//
// int S = QFontMetricsF(QApplication::font()).height();
// QImage pix( (*icons.begin()).pixmap(QSize(4*S,4*S)).toImage());
//
// QString embeddedImage;
// if(RsHtml::makeEmbeddedImage(pix.scaled(QSize(4*S,4*S), Qt::KeepAspectRatio, Qt::SmoothTransformation), embeddedImage, 8*S * 8*S))
// comment = "<table><tr><td>" + embeddedImage + "</td><td>" + comment + "</td></table>";
//
// return comment;
// }
2019-06-25 17:08:31 -04:00
return QVariant ( ) ;
}
2019-08-12 07:43:45 -04:00
QVariant RsFriendListModel : : sizeHintRole ( const EntryIndex & e , int col ) const
2019-06-25 17:08:31 -04:00
{
float factor = QFontMetricsF ( QApplication : : font ( ) ) . height ( ) / 14.0f ;
2019-08-12 07:43:45 -04:00
if ( e . type = = ENTRY_TYPE_NODE )
factor * = 3.0 ;
2019-06-25 17:08:31 -04:00
switch ( col )
{
default :
2019-06-28 05:12:44 -04:00
case COLUMN_THREAD_NAME : return QVariant ( QSize ( factor * 170 , factor * 14 ) ) ;
case COLUMN_THREAD_IP : return QVariant ( QSize ( factor * 75 , factor * 14 ) ) ;
case COLUMN_THREAD_ID : return QVariant ( QSize ( factor * 75 , factor * 14 ) ) ;
case COLUMN_THREAD_LAST_CONTACT : return QVariant ( QSize ( factor * 75 , factor * 14 ) ) ;
2019-06-25 17:08:31 -04:00
}
}
2019-08-12 05:20:53 -04:00
QVariant RsFriendListModel : : sortRole ( const EntryIndex & entry , int column ) const
2019-06-28 05:12:44 -04:00
{
2019-08-12 05:20:53 -04:00
switch ( column )
{
case COLUMN_THREAD_LAST_CONTACT :
{
switch ( entry . type )
{
case ENTRY_TYPE_PROFILE :
{
const HierarchicalProfileInformation * prof = getProfileInfo ( entry ) ;
2019-08-06 16:52:07 -04:00
2019-08-12 05:20:53 -04:00
if ( ! prof )
return QVariant ( ) ;
uint32_t last_contact = 0 ;
for ( uint32_t i = 0 ; i < prof - > child_node_indices . size ( ) ; + + i )
last_contact = std : : max ( last_contact , mLocations [ prof - > child_node_indices [ i ] ] . node_info . lastConnect ) ;
return QVariant ( last_contact ) ;
}
break ;
default :
return QVariant ( ) ;
}
}
break ;
default :
return displayRole ( entry , column ) ;
}
2019-06-25 17:08:31 -04:00
}
2019-08-12 06:49:04 -04:00
QVariant RsFriendListModel : : onlineRole ( const EntryIndex & e , int col ) const
2019-08-03 17:22:48 -04:00
{
switch ( e . type )
{
2019-08-12 06:49:04 -04:00
default :
2019-08-03 17:22:48 -04:00
case ENTRY_TYPE_GROUP :
2019-08-12 06:49:04 -04:00
{
const HierarchicalGroupInformation & g ( mGroups [ e . group_index ] ) ;
for ( uint32_t j = 0 ; j < g . child_profile_indices . size ( ) ; + + j )
{
const HierarchicalProfileInformation & prof = mProfiles [ g . child_profile_indices [ j ] ] ;
for ( uint32_t i = 0 ; i < prof . child_node_indices . size ( ) ; + + i )
if ( mLocations [ prof . child_node_indices [ i ] ] . node_info . state & RS_PEER_STATE_CONNECTED )
return QVariant ( true ) ;
}
return QVariant ( false ) ;
}
2019-08-03 17:22:48 -04:00
case ENTRY_TYPE_PROFILE :
2019-08-07 16:35:57 -04:00
{
const HierarchicalProfileInformation * prof = getProfileInfo ( e ) ;
if ( ! prof )
return QVariant ( ) ;
for ( uint32_t i = 0 ; i < prof - > child_node_indices . size ( ) ; + + i )
if ( mLocations [ prof - > child_node_indices [ i ] ] . node_info . state & RS_PEER_STATE_CONNECTED )
2019-08-12 06:49:04 -04:00
return QVariant ( true ) ;
2019-08-07 16:35:57 -04:00
return QVariant ( ) ;
}
2019-08-03 17:22:48 -04:00
break ;
case ENTRY_TYPE_NODE :
2019-08-07 16:35:57 -04:00
const HierarchicalNodeInformation * node = getNodeInfo ( e ) ;
2019-08-03 17:22:48 -04:00
if ( ! node )
return QVariant ( ) ;
2019-08-12 06:49:04 -04:00
return QVariant ( bool ( node - > node_info . state & RS_PEER_STATE_CONNECTED ) ) ;
}
}
QVariant RsFriendListModel : : fontRole ( const EntryIndex & e , int col ) const
{
2019-08-15 09:49:20 -04:00
# ifdef DEBUG_MODEL
2019-08-12 06:49:04 -04:00
std : : cerr < < " font role " < < e . type < < " , ( " < < ( int ) e . group_index < < " , " < < ( int ) e . profile_index < < " , " < < ( int ) e . node_index < < " ) col= " < < col < < " : " < < std : : endl ;
2019-08-15 09:49:20 -04:00
# endif
2019-08-12 06:49:04 -04:00
bool b = onlineRole ( e , col ) . toBool ( ) ;
2019-08-21 16:39:07 -04:00
if ( b )
2019-08-12 06:49:04 -04:00
{
2019-08-03 17:22:48 -04:00
QFont font ;
2019-08-12 06:49:04 -04:00
font . setBold ( b ) ;
2019-08-03 17:22:48 -04:00
return QVariant ( font ) ;
2019-08-12 06:49:04 -04:00
}
else
return QVariant ( ) ;
2019-08-03 17:22:48 -04:00
}
2019-08-17 09:25:32 -04:00
class AutoEndel
{
public :
~ AutoEndel ( ) { std : : cerr < < std : : endl ; }
} ;
2019-06-28 05:12:44 -04:00
QVariant RsFriendListModel : : displayRole ( const EntryIndex & e , int col ) const
2019-06-25 17:08:31 -04:00
{
2019-08-22 07:13:04 -04:00
# ifdef DEBUG_MODEL
2019-08-17 09:25:32 -04:00
std : : cerr < < " Display role " < < e . type < < " , ( " < < ( int ) e . group_index < < " , " < < ( int ) e . profile_index < < " , " < < ( int ) e . node_index < < " ) col= " < < col < < " : " ;
AutoEndel x ;
2019-08-15 09:49:20 -04:00
# endif
2019-07-28 03:12:55 -04:00
2019-06-28 05:12:44 -04:00
switch ( e . type )
2019-06-25 17:08:31 -04:00
{
2019-06-28 05:12:44 -04:00
case ENTRY_TYPE_GROUP :
2019-08-01 10:53:59 -04:00
{
2019-08-07 16:35:57 -04:00
const HierarchicalGroupInformation * group = getGroupInfo ( e ) ;
2019-06-25 17:08:31 -04:00
2019-08-11 08:44:58 -04:00
uint32_t nb_online = 0 ;
for ( uint32_t i = 0 ; i < group - > child_profile_indices . size ( ) ; + + i )
for ( uint32_t j = 0 ; j < mProfiles [ group - > child_profile_indices [ i ] ] . child_node_indices . size ( ) ; + + j )
if ( mLocations [ mProfiles [ group - > child_profile_indices [ i ] ] . child_node_indices [ j ] ] . node_info . state & RS_PEER_STATE_CONNECTED )
{
nb_online + + ;
break ; // only breaks the inner loop, on purpose.
}
2019-08-01 10:53:59 -04:00
if ( ! group )
return QVariant ( ) ;
2019-06-25 17:08:31 -04:00
2019-08-01 10:53:59 -04:00
switch ( col )
{
2019-08-01 17:55:42 -04:00
case COLUMN_THREAD_NAME :
2019-08-22 07:13:04 -04:00
# ifdef DEBUG_MODEL
2019-08-17 09:25:32 -04:00
std : : cerr < < group - > group_info . name . c_str ( ) ;
2019-08-15 09:49:20 -04:00
# endif
2019-08-11 08:44:58 -04:00
if ( ! group - > child_profile_indices . empty ( ) )
return QVariant ( QString : : fromUtf8 ( group - > group_info . name . c_str ( ) ) + " ( " + QString : : number ( nb_online ) + " / " + QString : : number ( group - > child_profile_indices . size ( ) ) + " ) " ) ;
else
return QVariant ( QString : : fromUtf8 ( group - > group_info . name . c_str ( ) ) ) ;
2019-06-25 17:08:31 -04:00
2019-08-22 07:13:04 -04:00
case COLUMN_THREAD_ID : return QVariant ( QString : : fromStdString ( group - > group_info . id . toStdString ( ) ) ) ;
2019-08-01 10:53:59 -04:00
default :
return QVariant ( ) ;
}
}
break ;
2019-06-25 17:08:31 -04:00
2019-08-01 10:53:59 -04:00
case ENTRY_TYPE_PROFILE :
2019-06-28 05:12:44 -04:00
{
2019-08-07 16:35:57 -04:00
const HierarchicalProfileInformation * profile = getProfileInfo ( e ) ;
2019-06-25 17:08:31 -04:00
2019-08-01 10:53:59 -04:00
if ( ! profile )
return QVariant ( ) ;
2019-08-22 07:13:04 -04:00
# ifdef DEBUG_MODEL
2019-08-17 09:25:32 -04:00
std : : cerr < < profile - > profile_info . name . c_str ( ) ;
# endif
2019-08-01 10:53:59 -04:00
switch ( col )
{
2019-08-07 16:35:57 -04:00
case COLUMN_THREAD_NAME : return QVariant ( QString : : fromUtf8 ( profile - > profile_info . name . c_str ( ) ) ) ;
case COLUMN_THREAD_ID : return QVariant ( QString : : fromStdString ( profile - > profile_info . gpg_id . toStdString ( ) ) ) ;
2019-08-01 10:53:59 -04:00
default :
return QVariant ( ) ;
}
}
break ;
2019-06-25 17:08:31 -04:00
2019-06-28 05:12:44 -04:00
case ENTRY_TYPE_NODE :
2019-08-07 16:35:57 -04:00
const HierarchicalNodeInformation * node = getNodeInfo ( e ) ;
2019-08-01 10:53:59 -04:00
if ( ! node )
2019-06-28 05:12:44 -04:00
return QVariant ( ) ;
2019-06-25 17:08:31 -04:00
2019-08-17 09:25:32 -04:00
# ifndef DEBUG_MODEL
std : : cerr < < node - > node_info . location . c_str ( ) ;
# endif
2019-06-28 05:12:44 -04:00
switch ( col )
{
2019-08-15 13:05:42 -04:00
case COLUMN_THREAD_NAME : if ( node - > node_info . location . empty ( ) )
return QVariant ( QString : : fromStdString ( node - > node_info . id . toStdString ( ) ) ) ;
{
std : : string css = rsMsgs - > getCustomStateString ( node - > node_info . id ) ;
2019-08-15 13:43:41 -04:00
if ( ! css . empty ( ) & & mDisplayStatusString )
2019-08-15 13:05:42 -04:00
return QVariant ( QString : : fromUtf8 ( node - > node_info . location . c_str ( ) ) + " \n " + QString : : fromUtf8 ( css . c_str ( ) ) ) ;
else
return QVariant ( QString : : fromUtf8 ( node - > node_info . location . c_str ( ) ) ) ;
}
2019-08-07 16:35:57 -04:00
case COLUMN_THREAD_LAST_CONTACT : return QVariant ( QDateTime : : fromTime_t ( node - > node_info . lastConnect ) . toString ( ) ) ;
case COLUMN_THREAD_IP : return QVariant ( ( node - > node_info . state & RS_PEER_STATE_CONNECTED ) ? StatusDefs : : connectStateIpString ( node - > node_info ) : QString ( " --- " ) ) ;
case COLUMN_THREAD_ID : return QVariant ( QString : : fromStdString ( node - > node_info . id . toStdString ( ) ) ) ;
2019-06-25 17:08:31 -04:00
2019-06-28 05:12:44 -04:00
default :
return QVariant ( ) ;
} break ;
2019-06-25 17:08:31 -04:00
2019-06-28 05:12:44 -04:00
return QVariant ( ) ;
2019-06-25 17:08:31 -04:00
}
}
2019-08-20 15:27:59 -04:00
// This function makes sure that the internal data gets updated. They are situations where the otification system cannot
// send the information about changes, such as when the computer is put on sleep.
2019-08-21 16:39:07 -04:00
void RsFriendListModel : : checkInternalData ( bool force )
2019-08-20 15:27:59 -04:00
{
2019-08-21 16:39:07 -04:00
rstime_t now = time ( NULL ) ;
if ( mLastInternalDataUpdate + MAX_INTERNAL_DATA_UPDATE_DELAY < now | | force )
updateInternalData ( ) ;
if ( mLastNodeUpdate + MAX_NODE_UPDATE_DELAY < now )
{
for ( uint32_t i = 0 ; i < mLocations . size ( ) ; + + i )
if ( mLocations [ i ] . last_update_ts + NODE_DETAILS_UPDATE_DELAY < now )
{
# ifdef DEBUG_MODEL
std : : cerr < < " Updating ID " < < node . node_info . id < < std : : endl ;
# endif
RsPeerId id ( mLocations [ i ] . node_info . id ) ; // this avoids zeroing the id field when writing the node data
rsPeers - > getPeerDetails ( id , mLocations [ i ] . node_info ) ;
mLocations [ i ] . last_update_ts = now ;
}
mLastNodeUpdate = now ;
}
2019-08-20 15:27:59 -04:00
}
2019-08-07 16:35:57 -04:00
const RsFriendListModel : : HierarchicalGroupInformation * RsFriendListModel : : getGroupInfo ( const EntryIndex & e ) const
2019-08-01 10:53:59 -04:00
{
if ( e . group_index > = mGroups . size ( ) )
return NULL ;
else
2019-08-07 16:35:57 -04:00
return & mGroups [ e . group_index ] ;
2019-08-01 10:53:59 -04:00
}
2019-08-07 16:35:57 -04:00
const RsFriendListModel : : HierarchicalProfileInformation * RsFriendListModel : : getProfileInfo ( const EntryIndex & e ) const
2019-08-01 10:53:59 -04:00
{
// First look into the relevant group, then for the correct profile in this group.
if ( e . type ! = ENTRY_TYPE_PROFILE )
return NULL ;
if ( e . group_index < 0xff )
{
const HierarchicalGroupInformation & group ( mGroups [ e . group_index ] ) ;
2019-08-02 09:40:11 -04:00
if ( e . profile_index > = group . child_profile_indices . size ( ) )
2019-08-01 10:53:59 -04:00
return NULL ;
2019-08-07 16:35:57 -04:00
return & mProfiles [ group . child_profile_indices [ e . profile_index ] ] ;
2019-08-01 10:53:59 -04:00
}
else
2019-08-07 16:35:57 -04:00
return & mProfiles [ e . profile_index ] ;
2019-08-01 10:53:59 -04:00
}
2019-08-07 16:35:57 -04:00
const RsFriendListModel : : HierarchicalNodeInformation * RsFriendListModel : : getNodeInfo ( const EntryIndex & e ) const
2019-08-01 10:53:59 -04:00
{
if ( e . type ! = ENTRY_TYPE_NODE )
return NULL ;
uint32_t pindex = 0 ;
if ( e . group_index < 0xff )
{
const HierarchicalGroupInformation & group ( mGroups [ e . group_index ] ) ;
2019-08-02 09:40:11 -04:00
if ( e . profile_index > = group . child_profile_indices . size ( ) )
2019-08-01 10:53:59 -04:00
return NULL ;
2019-08-02 09:40:11 -04:00
pindex = group . child_profile_indices [ e . profile_index ] ;
2019-08-01 10:53:59 -04:00
}
else
{
2019-08-02 09:40:11 -04:00
if ( e . profile_index > = mProfiles . size ( ) )
2019-08-01 10:53:59 -04:00
return NULL ;
2019-08-02 09:40:11 -04:00
pindex = e . profile_index ;
2019-08-01 10:53:59 -04:00
}
if ( e . node_index > = mProfiles [ pindex ] . child_node_indices . size ( ) )
return NULL ;
2019-08-03 17:22:48 -04:00
time_t now = time ( NULL ) ;
HierarchicalNodeInformation & node ( mLocations [ mProfiles [ pindex ] . child_node_indices [ e . node_index ] ] ) ;
2019-08-07 16:35:57 -04:00
return & node ;
2019-08-01 10:53:59 -04:00
}
2019-08-11 08:44:58 -04:00
bool RsFriendListModel : : getPeerOnlineStatus ( const EntryIndex & e ) const
2019-08-06 13:41:18 -04:00
{
2019-08-07 16:35:57 -04:00
const HierarchicalNodeInformation * noded = getNodeInfo ( e ) ;
2019-08-11 08:44:58 -04:00
return ( noded & & ( noded - > node_info . state & RS_PEER_STATE_CONNECTED ) ) ;
2019-08-06 13:41:18 -04:00
}
2019-08-01 10:53:59 -04:00
2019-08-12 07:43:45 -04:00
QVariant RsFriendListModel : : decorationRole ( const EntryIndex & entry , int col ) const
2019-06-28 05:12:44 -04:00
{
2019-08-12 08:17:00 -04:00
if ( col > 0 )
return QVariant ( ) ;
2019-08-12 07:43:45 -04:00
switch ( entry . type )
{
case ENTRY_TYPE_NODE :
{
const HierarchicalNodeInformation * hn = getNodeInfo ( entry ) ;
2019-06-25 17:08:31 -04:00
2019-08-12 07:43:45 -04:00
if ( ! hn )
return QVariant ( ) ;
QPixmap sslAvatar ;
AvatarDefs : : getAvatarFromSslId ( RsPeerId ( hn - > node_info . id . toStdString ( ) ) , sslAvatar ) ;
return QVariant ( QIcon ( sslAvatar ) ) ;
}
}
2019-06-28 05:12:44 -04:00
return QVariant ( ) ;
2019-06-25 17:08:31 -04:00
}
2019-06-28 05:12:44 -04:00
void RsFriendListModel : : clear ( )
2019-06-25 17:08:31 -04:00
{
preMods ( ) ;
2019-06-28 05:12:44 -04:00
mGroups . clear ( ) ;
mProfiles . clear ( ) ;
mLocations . clear ( ) ;
2019-08-01 10:53:59 -04:00
mTopLevel . clear ( ) ;
2019-06-25 17:08:31 -04:00
postMods ( ) ;
2019-06-28 05:12:44 -04:00
emit friendListChanged ( ) ;
}
2019-06-25 17:08:31 -04:00
static bool decreasing_time_comp ( const std : : pair < time_t , RsGxsMessageId > & e1 , const std : : pair < time_t , RsGxsMessageId > & e2 ) { return e2 . first < e1 . first ; }
2019-06-28 05:12:44 -04:00
void RsFriendListModel : : debug_dump ( ) const
2019-06-25 17:08:31 -04:00
{
2019-08-11 05:46:49 -04:00
std : : cerr < < " ==== FriendListModel Debug dump ==== " < < std : : endl ;
2019-08-01 17:55:42 -04:00
2019-08-11 05:46:49 -04:00
for ( uint32_t j = 0 ; j < mTopLevel . size ( ) ; + + j )
{
if ( mTopLevel [ j ] . type = = ENTRY_TYPE_GROUP )
2019-08-01 17:55:42 -04:00
{
2019-08-11 05:46:49 -04:00
const HierarchicalGroupInformation & hg ( mGroups [ mTopLevel [ j ] . group_index ] ) ;
std : : cerr < < " Group: " < < hg . group_info . name < < " , " ;
std : : cerr < < " children indices: " ; for ( uint32_t i = 0 ; i < hg . child_profile_indices . size ( ) ; + + i ) std : : cerr < < hg . child_profile_indices [ i ] < < " " ; std : : cerr < < std : : endl ;
2019-08-01 17:55:42 -04:00
2019-08-11 05:46:49 -04:00
for ( uint32_t i = 0 ; i < hg . child_profile_indices . size ( ) ; + + i )
{
uint32_t profile_index = hg . child_profile_indices [ i ] ;
2019-08-01 17:55:42 -04:00
2019-08-11 05:46:49 -04:00
std : : cerr < < " Profile " < < mProfiles [ profile_index ] . profile_info . gpg_id < < std : : endl ;
2019-08-01 17:55:42 -04:00
2019-08-11 05:46:49 -04:00
const HierarchicalProfileInformation & hprof ( mProfiles [ profile_index ] ) ;
for ( uint32_t k = 0 ; k < hprof . child_node_indices . size ( ) ; + + k )
std : : cerr < < " Node " < < mLocations [ hprof . child_node_indices [ k ] ] . node_info . id < < std : : endl ;
}
2019-08-01 17:55:42 -04:00
}
2019-08-11 05:46:49 -04:00
else if ( mTopLevel [ j ] . type = = ENTRY_TYPE_PROFILE )
{
const HierarchicalProfileInformation & hprof ( mProfiles [ mTopLevel [ j ] . profile_index ] ) ;
2019-08-01 17:55:42 -04:00
2019-08-11 05:46:49 -04:00
std : : cerr < < " Profile " < < hprof . profile_info . gpg_id < < std : : endl ;
for ( uint32_t k = 0 ; k < hprof . child_node_indices . size ( ) ; + + k )
std : : cerr < < " Node " < < mLocations [ hprof . child_node_indices [ k ] ] . node_info . id < < std : : endl ;
}
}
std : : cerr < < " ==================================== " < < std : : endl ;
2019-06-25 17:08:31 -04:00
}
2019-06-28 10:20:26 -04:00
bool RsFriendListModel : : getGroupData ( const QModelIndex & i , RsGroupInfo & data ) const
{
if ( ! i . isValid ( ) )
return false ;
EntryIndex e ;
2019-08-01 10:53:59 -04:00
if ( ! convertInternalIdToIndex ( i . internalId ( ) , e ) | | e . type ! = ENTRY_TYPE_GROUP )
2019-06-28 10:20:26 -04:00
return false ;
2019-08-07 16:35:57 -04:00
const HierarchicalGroupInformation * ginfo = getGroupInfo ( e ) ;
2019-08-01 10:53:59 -04:00
if ( ginfo )
{
2019-08-07 16:35:57 -04:00
data = ginfo - > group_info ;
2019-08-01 10:53:59 -04:00
return true ;
}
else
return false ;
2019-06-28 10:20:26 -04:00
}
bool RsFriendListModel : : getProfileData ( const QModelIndex & i , RsProfileDetails & data ) const
{
if ( ! i . isValid ( ) )
return false ;
EntryIndex e ;
2019-08-01 10:53:59 -04:00
if ( ! convertInternalIdToIndex ( i . internalId ( ) , e ) | | e . type ! = ENTRY_TYPE_PROFILE )
2019-06-28 10:20:26 -04:00
return false ;
2019-08-07 16:35:57 -04:00
const HierarchicalProfileInformation * gprof = getProfileInfo ( e ) ;
2019-08-01 10:53:59 -04:00
if ( gprof )
{
2019-08-07 16:35:57 -04:00
data = gprof - > profile_info ;
2019-08-01 10:53:59 -04:00
return true ;
}
else
return false ;
2019-06-28 10:20:26 -04:00
}
bool RsFriendListModel : : getNodeData ( const QModelIndex & i , RsNodeDetails & data ) const
{
if ( ! i . isValid ( ) )
return false ;
EntryIndex e ;
2019-08-01 10:53:59 -04:00
if ( ! convertInternalIdToIndex ( i . internalId ( ) , e ) | | e . type ! = ENTRY_TYPE_NODE )
2019-06-28 10:20:26 -04:00
return false ;
2019-08-07 16:35:57 -04:00
const HierarchicalNodeInformation * gnode = getNodeInfo ( e ) ;
2019-08-01 10:53:59 -04:00
if ( gnode )
{
2019-08-07 16:35:57 -04:00
data = gnode - > node_info ;
2019-08-01 10:53:59 -04:00
return true ;
}
else
return false ;
2019-06-28 10:20:26 -04:00
}
RsFriendListModel : : EntryType RsFriendListModel : : getType ( const QModelIndex & i ) const
{
if ( ! i . isValid ( ) )
return ENTRY_TYPE_UNKNOWN ;
EntryIndex e ;
if ( ! convertInternalIdToIndex ( i . internalId ( ) , e ) )
return ENTRY_TYPE_UNKNOWN ;
return e . type ;
}
2019-06-28 16:36:19 -04:00
2019-08-19 16:56:49 -04:00
std : : map < RsPgpId , uint32_t > : : const_iterator RsFriendListModel : : checkProfileIndex ( const RsPgpId & pgp_id , std : : map < RsPgpId , uint32_t > & pgp_indices , std : : vector < HierarchicalProfileInformation > & mProfiles , bool create )
{
auto it2 = pgp_indices . find ( pgp_id ) ;
if ( it2 = = pgp_indices . end ( ) )
{
if ( ! create )
{
std : : cerr < < " (EE) trying to display profile " < < pgp_id < < " that is actually not a friend. " < < std : : endl ;
return it2 ;
}
HierarchicalProfileInformation hprof ;
rsPeers - > getGPGDetails ( pgp_id , hprof . profile_info ) ;
pgp_indices [ pgp_id ] = mProfiles . size ( ) ;
mProfiles . push_back ( hprof ) ;
it2 = pgp_indices . find ( pgp_id ) ;
2019-08-22 07:30:15 -04:00
# ifdef DEBUG_MODEL
2019-08-19 16:56:49 -04:00
RsDbg ( ) < < " Creating profile pgp id = " < < pgp_id < < " ( " < < hprof . profile_info . name < < " ) " < < std : : endl ;
2019-08-22 07:30:15 -04:00
# endif
2019-08-19 16:56:49 -04:00
}
return it2 ;
}
2019-06-28 16:36:19 -04:00
void RsFriendListModel : : updateInternalData ( )
{
preMods ( ) ;
2019-08-01 10:53:59 -04:00
beginRemoveRows ( QModelIndex ( ) , 0 , mTopLevel . size ( ) - 1 ) ;
endRemoveRows ( ) ;
2019-07-28 03:12:55 -04:00
2019-06-28 16:36:19 -04:00
mGroups . clear ( ) ;
mProfiles . clear ( ) ;
2019-08-01 10:53:59 -04:00
mLocations . clear ( ) ;
2019-06-28 16:36:19 -04:00
2019-08-01 10:53:59 -04:00
mTopLevel . clear ( ) ;
2019-06-29 11:50:13 -04:00
// create a map of profiles and groups
2019-08-19 16:56:49 -04:00
std : : map < RsPgpId , uint32_t > pgp_indices ;
// parse PGP friends that may or may not have a known location. Create the associated data.
2019-06-29 11:50:13 -04:00
2019-08-19 16:56:49 -04:00
std : : list < RsPgpId > pgp_friends ;
rsPeers - > getGPGAcceptedList ( pgp_friends ) ;
for ( auto it ( pgp_friends . begin ( ) ) ; it ! = pgp_friends . end ( ) ; + + it )
checkProfileIndex ( * it , pgp_indices , mProfiles , true ) ;
2019-06-29 17:55:38 -04:00
2019-08-19 16:56:49 -04:00
// Now parse peer ids and look for the associated PGP id. If not found, raise an error.
2019-08-22 07:30:15 -04:00
# ifdef DEBUG_MODEL
2019-08-01 17:55:42 -04:00
RsDbg ( ) < < " Updating Nodes information: " < < std : : endl ;
2019-08-22 07:30:15 -04:00
# endif
2019-08-01 10:53:59 -04:00
std : : list < RsPeerId > peer_ids ;
rsPeers - > getFriendList ( peer_ids ) ;
2019-06-28 16:36:19 -04:00
2019-08-01 10:53:59 -04:00
for ( auto it ( peer_ids . begin ( ) ) ; it ! = peer_ids . end ( ) ; + + it )
2019-06-29 11:50:13 -04:00
{
2019-08-01 10:53:59 -04:00
// profiles
2019-06-28 16:36:19 -04:00
2019-08-01 10:53:59 -04:00
HierarchicalNodeInformation hnode ;
rsPeers - > getPeerDetails ( * it , hnode . node_info ) ;
2019-06-28 16:36:19 -04:00
2019-08-20 08:57:44 -04:00
// If the Peer ID belong to our own profile, we add our own profile to the list. Otherwise we do not display it in the friend list.
auto it2 = checkProfileIndex ( hnode . node_info . gpg_id , pgp_indices , mProfiles , hnode . node_info . gpg_id = = rsPeers - > getGPGOwnId ( ) ) ;
2019-06-28 16:36:19 -04:00
2019-08-01 10:53:59 -04:00
if ( it2 = = pgp_indices . end ( ) )
2019-08-19 16:56:49 -04:00
continue ;
2019-08-17 09:25:32 -04:00
2019-08-01 10:53:59 -04:00
mProfiles [ it2 - > second ] . child_node_indices . push_back ( mLocations . size ( ) ) ;
mLocations . push_back ( hnode ) ;
}
2019-06-28 16:36:19 -04:00
2019-08-17 09:25:32 -04:00
// finally, parse groups
2019-08-11 05:46:49 -04:00
if ( mDisplayGroups )
{
// groups
2019-06-28 16:36:19 -04:00
2019-08-11 05:46:49 -04:00
std : : list < RsGroupInfo > groupInfoList ;
rsPeers - > getGroupInfoList ( groupInfoList ) ;
2019-06-28 16:36:19 -04:00
2019-08-22 07:30:15 -04:00
# ifdef DEBUG_MODEL
2019-08-11 05:46:49 -04:00
RsDbg ( ) < < " Updating Groups information: " < < std : : endl ;
2019-08-22 07:30:15 -04:00
# endif
2019-06-28 16:36:19 -04:00
2019-08-11 05:46:49 -04:00
for ( auto it ( groupInfoList . begin ( ) ) ; it ! = groupInfoList . end ( ) ; + + it )
{
// first, fill the group hierarchical info
2019-06-29 11:50:13 -04:00
2019-08-11 05:46:49 -04:00
HierarchicalGroupInformation hgroup ;
hgroup . group_info = * it ;
2019-06-29 11:50:13 -04:00
2019-08-22 07:30:15 -04:00
# ifdef DEBUG_MODEL
2019-08-11 05:46:49 -04:00
RsDbg ( ) < < " Group \" " < < hgroup . group_info . name < < " \" " < < std : : endl ;
2019-08-22 07:30:15 -04:00
# endif
2019-07-27 17:42:39 -04:00
2019-08-11 05:46:49 -04:00
for ( auto it2 ( ( * it ) . peerIds . begin ( ) ) ; it2 ! = ( * it ) . peerIds . end ( ) ; + + it2 )
{
// Then for each peer in this group, make sure that the peer is already known, and if not create it
2019-06-29 11:50:13 -04:00
2019-08-19 16:56:49 -04:00
auto it3 = checkProfileIndex ( * it2 , pgp_indices , mProfiles , false ) ;
2019-06-29 17:55:38 -04:00
2019-08-11 05:46:49 -04:00
if ( it3 = = pgp_indices . end ( ) ) // not found
2019-08-19 16:56:49 -04:00
continue ;
2019-07-28 03:12:55 -04:00
2019-08-11 05:46:49 -04:00
hgroup . child_profile_indices . push_back ( it3 - > second ) ;
}
2019-06-29 17:55:38 -04:00
2019-08-11 05:46:49 -04:00
mGroups . push_back ( hgroup ) ;
}
}
2019-06-29 17:55:38 -04:00
2019-08-01 10:53:59 -04:00
// now the top level list
2019-07-27 17:42:39 -04:00
2019-08-22 07:30:15 -04:00
# ifdef DEBUG_MODEL
2019-08-17 09:25:32 -04:00
RsDbg ( ) < < " Creating top level list " < < std : : endl ;
2019-08-22 07:30:15 -04:00
# endif
2019-08-17 09:25:32 -04:00
2019-08-01 10:53:59 -04:00
mTopLevel . clear ( ) ;
std : : set < RsPgpId > already_in_a_group ;
2019-06-29 17:55:38 -04:00
2019-08-01 10:53:59 -04:00
if ( mDisplayGroups ) // in this case, we list all groups at the top level followed by the profiles without parent group
{
for ( uint32_t i = 0 ; i < mGroups . size ( ) ; + + i )
{
2019-08-22 07:30:15 -04:00
# ifdef DEBUG_MODEL
2019-08-17 09:25:32 -04:00
RsDbg ( ) < < " Group " < < mGroups [ i ] . group_info . name < < std : : endl ;
2019-08-22 07:30:15 -04:00
# endif
2019-08-17 09:25:32 -04:00
2019-08-01 10:53:59 -04:00
EntryIndex e ;
e . type = ENTRY_TYPE_GROUP ;
e . group_index = i ;
2019-06-29 17:55:38 -04:00
2019-08-01 10:53:59 -04:00
mTopLevel . push_back ( e ) ;
2019-08-15 09:54:16 -04:00
for ( uint32_t j = 0 ; j < mGroups [ i ] . child_profile_indices . size ( ) ; + + j )
already_in_a_group . insert ( mProfiles [ mGroups [ i ] . child_profile_indices [ j ] ] . profile_info . gpg_id ) ;
2019-06-29 11:50:13 -04:00
}
}
2019-08-01 10:53:59 -04:00
for ( uint32_t i = 0 ; i < mProfiles . size ( ) ; + + i )
if ( already_in_a_group . find ( mProfiles [ i ] . profile_info . gpg_id ) = = already_in_a_group . end ( ) )
{
2019-08-22 07:30:15 -04:00
# ifdef DEBUG_MODEL
2019-08-17 09:25:32 -04:00
RsDbg ( ) < < " Profile " < < mProfiles [ i ] . profile_info . name < < std : : endl ;
2019-08-22 07:30:15 -04:00
# endif
2019-08-17 09:25:32 -04:00
2019-08-01 10:53:59 -04:00
EntryIndex e ;
e . type = ENTRY_TYPE_PROFILE ;
e . profile_index = i ;
2019-08-02 09:40:11 -04:00
e . group_index = 0xff ;
2019-08-01 10:53:59 -04:00
mTopLevel . push_back ( e ) ;
}
// finally, tell the model client that layout has changed.
2019-08-11 05:46:49 -04:00
beginInsertRows ( QModelIndex ( ) , 0 , mTopLevel . size ( ) - 1 ) ;
2019-07-28 03:12:55 -04:00
endInsertRows ( ) ;
2019-06-28 16:36:19 -04:00
postMods ( ) ;
2019-08-20 15:27:59 -04:00
mLastInternalDataUpdate = time ( NULL ) ;
2019-06-28 16:36:19 -04:00
}