2019-09-01 19:46:12 +00:00
/*
* Squawk messenger .
* Copyright ( C ) 2019 Yury Gubich < blue @ macaw . me >
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 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 General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2019-03-31 21:05:09 +00:00
# include "roster.h"
2019-04-03 21:23:51 +00:00
# include <QDebug>
2019-04-02 21:58:43 +00:00
# include <QIcon>
2019-04-05 15:12:59 +00:00
# include <QFont>
2019-03-31 21:05:09 +00:00
Models : : Roster : : Roster ( QObject * parent ) :
QAbstractItemModel ( parent ) ,
2019-04-03 18:15:36 +00:00
accountsModel ( new Accounts ( ) ) ,
root ( new Item ( Item : : root , { { " name " , " root " } } ) ) ,
accounts ( ) ,
2019-04-03 21:23:51 +00:00
groups ( ) ,
2021-04-18 12:49:20 +00:00
contacts ( )
2019-03-31 21:05:09 +00:00
{
2019-10-23 14:49:56 +00:00
connect ( accountsModel , & Accounts : : dataChanged , this , & Roster : : onAccountDataChanged ) ;
connect ( root , & Item : : childChanged , this , & Roster : : onChildChanged ) ;
connect ( root , & Item : : childIsAboutToBeInserted , this , & Roster : : onChildIsAboutToBeInserted ) ;
connect ( root , & Item : : childInserted , this , & Roster : : onChildInserted ) ;
connect ( root , & Item : : childIsAboutToBeRemoved , this , & Roster : : onChildIsAboutToBeRemoved ) ;
connect ( root , & Item : : childRemoved , this , & Roster : : onChildRemoved ) ;
connect ( root , & Item : : childIsAboutToBeMoved , this , & Roster : : onChildIsAboutToBeMoved ) ;
connect ( root , & Item : : childMoved , this , & Roster : : onChildMoved ) ;
2019-03-31 21:05:09 +00:00
}
Models : : Roster : : ~ Roster ( )
{
2019-04-03 18:15:36 +00:00
delete accountsModel ;
2019-03-31 21:05:09 +00:00
delete root ;
}
void Models : : Roster : : addAccount ( const QMap < QString , QVariant > & data )
{
2019-04-07 14:02:41 +00:00
Account * acc = new Account ( data ) ;
2021-05-16 21:52:59 +00:00
connect ( acc , & Account : : reconnected , this , & Roster : : onAccountReconnected ) ;
2019-03-31 21:05:09 +00:00
root - > appendChild ( acc ) ;
2019-04-03 15:09:29 +00:00
accounts . insert ( std : : make_pair ( acc - > getName ( ) , acc ) ) ;
2019-04-03 18:15:36 +00:00
accountsModel - > addAccount ( acc ) ;
2019-03-31 21:05:09 +00:00
}
QVariant Models : : Roster : : data ( const QModelIndex & index , int role ) const
{
if ( ! index . isValid ( ) ) {
return QVariant ( ) ;
}
QVariant result ;
2019-04-02 21:58:43 +00:00
Item * item = static_cast < Item * > ( index . internalPointer ( ) ) ;
2020-04-17 23:17:47 +00:00
if ( item - > type = = Item : : reference ) {
item = static_cast < Reference * > ( item ) - > dereference ( ) ;
}
2019-03-31 21:05:09 +00:00
switch ( role ) {
case Qt : : DisplayRole :
{
2019-10-16 19:38:35 +00:00
if ( index . column ( ) ! = 0 ) {
break ;
}
2019-06-22 20:37:22 +00:00
switch ( item - > type ) {
case Item : : group : {
Group * gr = static_cast < Group * > ( item ) ;
QString str ( " " ) ;
str + = gr - > getName ( ) ;
unsigned int amount = gr - > getUnreadMessages ( ) ;
if ( amount > 0 ) {
2019-10-05 11:27:39 +00:00
str + = QString ( " ( " ) + tr ( " New messages " ) + " ) " ;
2019-06-22 20:37:22 +00:00
}
result = str ;
}
break ;
default :
result = item - > data ( index . column ( ) ) ;
break ;
}
2019-03-31 21:05:09 +00:00
}
break ;
2019-04-02 21:58:43 +00:00
case Qt : : DecorationRole :
switch ( item - > type ) {
2019-07-11 08:51:52 +00:00
case Item : : account : {
2019-10-16 19:38:35 +00:00
quint8 col = index . column ( ) ;
2019-04-03 18:15:36 +00:00
Account * acc = static_cast < Account * > ( item ) ;
2019-10-16 19:38:35 +00:00
if ( col = = 0 ) {
result = acc - > getStatusIcon ( false ) ;
} else if ( col = = 1 ) {
QString path = acc - > getAvatarPath ( ) ;
2019-10-24 09:42:38 +00:00
2019-10-16 19:38:35 +00:00
if ( path . size ( ) > 0 ) {
result = QIcon ( path ) ;
}
}
2019-04-02 21:58:43 +00:00
}
break ;
2019-07-11 08:51:52 +00:00
case Item : : contact : {
2019-04-05 15:12:59 +00:00
Contact * contact = static_cast < Contact * > ( item ) ;
2019-10-16 19:38:35 +00:00
quint8 col = index . column ( ) ;
if ( col = = 0 ) {
result = contact - > getStatusIcon ( false ) ;
} else if ( col = = 1 ) {
if ( contact - > getAvatarState ( ) ! = Shared : : Avatar : : empty ) {
result = QIcon ( contact - > getAvatarPath ( ) ) ;
}
}
2019-04-07 14:02:41 +00:00
}
break ;
2019-07-11 08:51:52 +00:00
case Item : : presence : {
2019-10-16 19:38:35 +00:00
if ( index . column ( ) ! = 0 ) {
break ;
}
2019-04-07 14:02:41 +00:00
Presence * presence = static_cast < Presence * > ( item ) ;
2019-06-23 21:09:39 +00:00
result = presence - > getStatusIcon ( false ) ;
2019-04-05 15:12:59 +00:00
}
break ;
2019-07-11 08:51:52 +00:00
case Item : : room : {
2019-12-17 16:54:53 +00:00
quint8 col = index . column ( ) ;
2019-07-11 08:51:52 +00:00
Room * room = static_cast < Room * > ( item ) ;
2019-12-17 16:54:53 +00:00
if ( col = = 0 ) {
result = room - > getStatusIcon ( false ) ;
} else if ( col = = 1 ) {
QString path = room - > getAvatarPath ( ) ;
if ( path . size ( ) > 0 ) {
result = QIcon ( path ) ;
}
}
2019-07-11 08:51:52 +00:00
}
break ;
2019-09-03 20:28:58 +00:00
case Item : : participant : {
2019-12-30 20:22:04 +00:00
quint8 col = index . column ( ) ;
Participant * p = static_cast < Participant * > ( item ) ;
if ( col = = 0 ) {
result = p - > getStatusIcon ( false ) ;
} else if ( col = = 1 ) {
QString path = p - > getAvatarPath ( ) ;
if ( path . size ( ) > 0 ) {
result = QIcon ( path ) ;
}
}
2019-10-16 19:38:35 +00:00
if ( index . column ( ) ! = 0 ) {
break ;
}
2019-12-30 20:22:04 +00:00
2019-09-03 20:28:58 +00:00
}
break ;
2019-04-02 21:58:43 +00:00
default :
break ;
}
break ;
2019-04-05 15:12:59 +00:00
case Qt : : FontRole :
switch ( item - > type ) {
case Item : : account : {
QFont font ;
font . setBold ( true ) ;
result = font ;
}
break ;
case Item : : group : {
QFont font ;
font . setItalic ( true ) ;
result = font ;
}
break ;
default :
break ;
}
2019-06-21 19:33:38 +00:00
break ;
case Qt : : ToolTipRole :
switch ( item - > type ) {
case Item : : account : {
Account * acc = static_cast < Account * > ( item ) ;
2020-04-03 22:28:15 +00:00
result = Shared : : Global : : getName ( acc - > getAvailability ( ) ) ;
2019-06-21 19:33:38 +00:00
}
break ;
case Item : : contact : {
Contact * contact = static_cast < Contact * > ( item ) ;
2019-06-22 20:37:22 +00:00
QString str ( " " ) ;
2019-06-21 19:33:38 +00:00
int mc = contact - > getMessagesCount ( ) ;
if ( mc > 0 ) {
2019-10-05 11:27:39 +00:00
str + = QString ( tr ( " New messages: " ) ) + std : : to_string ( mc ) . c_str ( ) + " \n " ;
2019-06-21 19:33:38 +00:00
}
2019-10-05 11:27:39 +00:00
str + = tr ( " Jabber ID: " ) + contact - > getJid ( ) + " \n " ;
2019-06-21 19:33:38 +00:00
Shared : : SubscriptionState ss = contact - > getState ( ) ;
2020-04-03 22:28:15 +00:00
if ( ss = = Shared : : SubscriptionState : : both | | ss = = Shared : : SubscriptionState : : to ) {
2019-06-21 19:33:38 +00:00
Shared : : Availability av = contact - > getAvailability ( ) ;
2020-04-03 22:28:15 +00:00
str + = tr ( " Availability: " ) + Shared : : Global : : getName ( av ) ;
if ( av ! = Shared : : Availability : : offline ) {
2019-06-21 19:33:38 +00:00
QString s = contact - > getStatus ( ) ;
if ( s . size ( ) > 0 ) {
2019-10-05 11:27:39 +00:00
str + = " \n " + tr ( " Status: " ) + s ;
2019-06-21 19:33:38 +00:00
}
}
2020-04-03 22:28:15 +00:00
str + = " \n " + tr ( " Subscription: " ) + Shared : : Global : : getName ( ss ) ;
2019-06-21 19:33:38 +00:00
} else {
2020-04-03 22:28:15 +00:00
str + = tr ( " Subscription: " ) + Shared : : Global : : getName ( ss ) ;
2019-06-21 19:33:38 +00:00
}
result = str ;
}
break ;
case Item : : presence : {
Presence * contact = static_cast < Presence * > ( item ) ;
2020-08-11 22:49:51 +00:00
QString str ;
2019-06-21 19:33:38 +00:00
Shared : : Availability av = contact - > getAvailability ( ) ;
2020-04-03 22:28:15 +00:00
str + = tr ( " Availability: " ) + Shared : : Global : : getName ( av ) ;
2019-06-21 19:33:38 +00:00
QString s = contact - > getStatus ( ) ;
if ( s . size ( ) > 0 ) {
2019-10-05 11:27:39 +00:00
str + = " \n " + tr ( " Status: " ) + s ;
2019-06-21 19:33:38 +00:00
}
2019-09-03 20:28:58 +00:00
result = str ;
}
break ;
case Item : : participant : {
Participant * p = static_cast < Participant * > ( item ) ;
2020-08-11 22:49:51 +00:00
QString str ;
2019-09-03 20:28:58 +00:00
Shared : : Availability av = p - > getAvailability ( ) ;
2020-04-03 22:28:15 +00:00
str + = tr ( " Availability: " ) + Shared : : Global : : getName ( av ) + " \n " ;
2019-09-03 20:28:58 +00:00
QString s = p - > getStatus ( ) ;
if ( s . size ( ) > 0 ) {
2019-10-05 11:27:39 +00:00
str + = tr ( " Status: " ) + s + " \n " ;
2019-09-03 20:28:58 +00:00
}
2020-04-03 22:28:15 +00:00
str + = tr ( " Affiliation: " ) + Shared : : Global : : getName ( p - > getAffiliation ( ) ) + " \n " ;
str + = tr ( " Role: " ) + Shared : : Global : : getName ( p - > getRole ( ) ) ;
2019-09-03 20:28:58 +00:00
2019-06-22 20:37:22 +00:00
result = str ;
}
break ;
case Item : : group : {
Group * gr = static_cast < Group * > ( item ) ;
unsigned int count = gr - > getUnreadMessages ( ) ;
QString str ( " " ) ;
if ( count > 0 ) {
2019-10-05 11:27:39 +00:00
str + = tr ( " New messages: " ) + std : : to_string ( count ) . c_str ( ) + " \n " ;
2019-06-22 20:37:22 +00:00
}
2019-10-05 11:27:39 +00:00
str + = tr ( " Online contacts: " ) + std : : to_string ( gr - > getOnlineContacts ( ) ) . c_str ( ) + " \n " ;
str + = tr ( " Total contacts: " ) + std : : to_string ( gr - > childCount ( ) ) . c_str ( ) ;
2019-06-21 19:33:38 +00:00
result = str ;
}
break ;
2019-07-11 08:51:52 +00:00
case Item : : room : {
Room * rm = static_cast < Room * > ( item ) ;
2020-08-11 22:49:51 +00:00
unsigned int count = rm - > getMessagesCount ( ) ;
2019-07-11 08:51:52 +00:00
QString str ( " " ) ;
if ( count > 0 ) {
2019-10-05 11:27:39 +00:00
str + = tr ( " New messages: " ) + std : : to_string ( count ) . c_str ( ) + " \n " ;
2019-07-11 08:51:52 +00:00
}
2019-12-17 16:54:53 +00:00
str + = tr ( " Jabber ID: " ) + rm - > getJid ( ) + " \n " ;
2019-10-05 11:27:39 +00:00
str + = tr ( " Subscription: " ) + rm - > getStatusText ( ) ;
2019-09-03 20:28:58 +00:00
if ( rm - > getJoined ( ) ) {
2019-10-05 11:27:39 +00:00
str + = QString ( " \n " ) + tr ( " Members: " ) + std : : to_string ( rm - > childCount ( ) ) . c_str ( ) ;
2019-09-03 20:28:58 +00:00
}
2019-07-11 08:51:52 +00:00
result = str ;
}
break ;
2019-06-21 19:33:38 +00:00
default :
result = " " ;
break ;
}
break ;
2022-04-12 20:33:10 +00:00
case Qt : : ForegroundRole :
switch ( item - > type ) {
case Item : : account : {
Account * acc = static_cast < Account * > ( item ) ;
if ( ! acc - > getActive ( ) ) {
result = qApp - > palette ( ) . brush ( QPalette : : Disabled , QPalette : : Text ) ;
}
}
break ;
default :
break ;
}
2019-03-31 21:05:09 +00:00
default :
break ;
}
return result ;
}
int Models : : Roster : : columnCount ( const QModelIndex & parent ) const
{
if ( parent . isValid ( ) ) {
return static_cast < Item * > ( parent . internalPointer ( ) ) - > columnCount ( ) ;
} else {
return root - > columnCount ( ) ;
}
}
2019-04-02 21:58:43 +00:00
void Models : : Roster : : updateAccount ( const QString & account , const QString & field , const QVariant & value )
{
std : : map < QString , Account * > : : iterator itr = accounts . find ( account ) ;
if ( itr ! = accounts . end ( ) ) {
Account * acc = itr - > second ;
2019-04-03 18:15:36 +00:00
acc - > update ( field , value ) ;
2019-04-02 21:58:43 +00:00
}
}
2019-03-31 21:05:09 +00:00
Qt : : ItemFlags Models : : Roster : : flags ( const QModelIndex & index ) const
{
if ( ! index . isValid ( ) ) {
2020-07-29 20:26:56 +00:00
return Qt : : ItemFlags ( ) ;
2019-03-31 21:05:09 +00:00
}
return QAbstractItemModel : : flags ( index ) ;
}
int Models : : Roster : : rowCount ( const QModelIndex & parent ) const
{
Item * parentItem ;
if ( ! parent . isValid ( ) ) {
parentItem = root ;
} else {
parentItem = static_cast < Item * > ( parent . internalPointer ( ) ) ;
}
return parentItem - > childCount ( ) ;
}
QVariant Models : : Roster : : headerData ( int section , Qt : : Orientation orientation , int role ) const
{
return QVariant ( ) ;
}
QModelIndex Models : : Roster : : parent ( const QModelIndex & child ) const
{
if ( ! child . isValid ( ) ) {
return QModelIndex ( ) ;
}
Item * childItem = static_cast < Item * > ( child . internalPointer ( ) ) ;
2019-04-02 21:58:43 +00:00
if ( childItem = = root ) {
return QModelIndex ( ) ;
}
2019-03-31 21:05:09 +00:00
Item * parentItem = childItem - > parentItem ( ) ;
if ( parentItem = = root ) {
2019-05-30 09:36:21 +00:00
return createIndex ( 0 , 0 , parentItem ) ;
2019-03-31 21:05:09 +00:00
}
return createIndex ( parentItem - > row ( ) , 0 , parentItem ) ;
}
QModelIndex Models : : Roster : : index ( int row , int column , const QModelIndex & parent ) const
{
if ( ! hasIndex ( row , column , parent ) ) {
return QModelIndex ( ) ;
}
Item * parentItem ;
if ( ! parent . isValid ( ) ) {
parentItem = root ;
} else {
parentItem = static_cast < Item * > ( parent . internalPointer ( ) ) ;
}
Item * childItem = parentItem - > child ( row ) ;
if ( childItem ) {
return createIndex ( row , column , childItem ) ;
} else {
return QModelIndex ( ) ;
}
}
Models : : Roster : : ElId : : ElId ( const QString & p_account , const QString & p_name ) :
account ( p_account ) ,
name ( p_name )
2019-04-03 18:15:36 +00:00
{ }
2019-03-31 21:05:09 +00:00
bool Models : : Roster : : ElId : : operator < ( const Models : : Roster : : ElId & other ) const
{
if ( account = = other . account ) {
return name < other . name ;
} else {
return account < other . account ;
}
}
2019-04-02 21:58:43 +00:00
2020-04-11 20:00:15 +00:00
bool Models : : Roster : : ElId : : operator ! = ( const Models : : Roster : : ElId & other ) const
{
return ! ( operator = = ( other ) ) ;
}
bool Models : : Roster : : ElId : : operator = = ( const Models : : Roster : : ElId & other ) const
{
return ( account = = other . account ) & & ( name = = other . name ) ;
}
2019-04-03 18:15:36 +00:00
void Models : : Roster : : onAccountDataChanged ( const QModelIndex & tl , const QModelIndex & br , const QVector < int > & roles )
{
if ( tl . column ( ) = = 0 ) {
emit dataChanged ( tl , br , roles ) ;
} else if ( tl . column ( ) = = 2 ) {
int row = tl . row ( ) ;
Account * acc = accountsModel - > getAccount ( row ) ;
emit dataChanged ( createIndex ( row , 0 , acc ) , createIndex ( br . row ( ) , 0 , acc ) , roles ) ;
}
}
2019-04-03 21:23:51 +00:00
void Models : : Roster : : addGroup ( const QString & account , const QString & name )
{
2019-04-05 15:12:59 +00:00
ElId id ( account , name ) ;
2019-06-22 20:37:22 +00:00
std : : map < ElId , Group * > : : const_iterator gItr = groups . find ( id ) ;
2019-04-05 15:12:59 +00:00
if ( gItr ! = groups . end ( ) ) {
qDebug ( ) < < " An attempt to add group " < < name < < " to account " < < account < < " which already exists there, skipping " ;
return ;
}
2019-04-03 21:23:51 +00:00
std : : map < QString , Account * > : : iterator itr = accounts . find ( account ) ;
if ( itr ! = accounts . end ( ) ) {
Account * acc = itr - > second ;
2019-06-22 20:37:22 +00:00
Group * group = new Group ( { { " name " , name } } ) ;
2019-04-05 15:12:59 +00:00
groups . insert ( std : : make_pair ( id , group ) ) ;
2019-07-11 08:51:52 +00:00
acc - > appendChild ( group ) ;
2019-04-03 21:23:51 +00:00
} else {
qDebug ( ) < < " An attempt to add group " < < name < < " to non existing account " < < account < < " , skipping " ;
}
}
2019-04-07 20:14:15 +00:00
void Models : : Roster : : addContact ( const QString & account , const QString & jid , const QString & group , const QMap < QString , QVariant > & data )
2019-04-03 21:23:51 +00:00
{
Item * parent ;
2019-04-05 15:12:59 +00:00
Account * acc ;
2020-04-17 23:17:47 +00:00
Contact * contact ;
Reference * ref = 0 ;
2019-04-05 15:12:59 +00:00
ElId id ( account , jid ) ;
{
2019-04-03 21:23:51 +00:00
std : : map < QString , Account * > : : iterator itr = accounts . find ( account ) ;
if ( itr = = accounts . end ( ) ) {
2019-09-28 14:30:16 +00:00
qDebug ( ) < < " An attempt to add a contact " < < jid < < " to non existing account " < < account < < " , skipping " ;
2019-04-03 21:23:51 +00:00
return ;
}
2019-04-05 15:12:59 +00:00
acc = itr - > second ;
}
2020-04-17 23:17:47 +00:00
{
std : : map < ElId , Contact * > : : iterator itr = contacts . find ( id ) ;
if ( itr = = contacts . end ( ) ) {
contact = new Contact ( acc , jid , data ) ;
2020-08-11 22:49:51 +00:00
connect ( contact , & Contact : : requestArchive , this , & Roster : : onElementRequestArchive ) ;
2021-04-18 12:49:20 +00:00
connect ( contact , & Contact : : fileDownloadRequest , this , & Roster : : fileDownloadRequest ) ;
2021-04-27 19:29:15 +00:00
connect ( contact , & Contact : : unnoticedMessage , this , & Roster : : unnoticedMessage ) ;
2021-04-28 20:26:19 +00:00
connect ( contact , & Contact : : localPathInvalid , this , & Roster : : localPathInvalid ) ;
2020-04-17 23:17:47 +00:00
contacts . insert ( std : : make_pair ( id , contact ) ) ;
} else {
contact = itr - > second ;
}
2019-09-28 14:30:16 +00:00
}
2020-04-17 23:17:47 +00:00
if ( group = = " " ) {
if ( acc - > getContact ( jid ) ! = - 1 ) {
2019-09-28 14:30:16 +00:00
qDebug ( ) < < " An attempt to add a contact " < < jid < < " to the ungrouped contact set of account " < < account < < " for the second time, skipping " ;
return ;
} else {
parent = acc ;
2019-04-05 15:12:59 +00:00
}
2019-04-03 21:23:51 +00:00
} else {
2019-06-22 20:37:22 +00:00
std : : map < ElId , Group * > : : iterator itr = groups . find ( { account , group } ) ;
2019-04-03 21:23:51 +00:00
if ( itr = = groups . end ( ) ) {
2019-09-28 14:30:16 +00:00
qDebug ( ) < < " An attempt to add a contact " < < jid < < " to non existing group " < < group < < " , adding group " ;
addGroup ( account , group ) ;
itr = groups . find ( { account , group } ) ;
2019-04-03 21:23:51 +00:00
}
2019-04-05 15:12:59 +00:00
2019-04-03 21:23:51 +00:00
parent = itr - > second ;
2019-04-05 15:12:59 +00:00
2020-04-17 23:17:47 +00:00
if ( parent - > getContact ( jid ) ! = - 1 ) {
qDebug ( ) < < " An attempt to add a contact " < < jid < < " to the group " < < group < < " for the second time, skipping " ;
return ;
2019-04-05 15:12:59 +00:00
}
2020-04-17 23:17:47 +00:00
int refIndex = acc - > getContact ( jid ) ;
if ( refIndex ! = - 1 ) { //checking if that contact is among ugrouped
qDebug ( ) < < " An attempt to add a already existing contact " < < jid
< < " to the group " < < group
< < " , contact will be moved from ungrouped contacts of " < < account ;
ref = static_cast < Reference * > ( acc - > child ( refIndex ) ) ;
acc - > removeChild ( refIndex ) ;
2019-04-05 15:12:59 +00:00
}
2019-04-03 21:23:51 +00:00
}
2020-04-17 23:17:47 +00:00
if ( ref = = 0 ) {
ref = new Reference ( contact ) ;
2019-09-28 14:30:16 +00:00
}
2020-04-17 23:17:47 +00:00
parent - > appendChild ( ref ) ;
2019-04-03 21:23:51 +00:00
}
void Models : : Roster : : removeGroup ( const QString & account , const QString & name )
{
2019-04-05 15:12:59 +00:00
ElId id ( account , name ) ;
2019-06-22 20:37:22 +00:00
std : : map < ElId , Group * > : : const_iterator gItr = groups . find ( id ) ;
2019-04-05 15:12:59 +00:00
if ( gItr = = groups . end ( ) ) {
qDebug ( ) < < " An attempt to remove group " < < name < < " from account " < < account < < " which doesn't exist there, skipping " ;
return ;
}
2019-06-22 20:37:22 +00:00
Group * item = gItr - > second ;
2019-04-05 15:12:59 +00:00
Item * parent = item - > parentItem ( ) ;
int row = item - > row ( ) ;
parent - > removeChild ( row ) ;
2020-04-17 23:17:47 +00:00
std : : deque < Reference * > toInsert ;
2019-04-05 15:12:59 +00:00
for ( int i = 0 ; item - > childCount ( ) > 0 ; + + i ) {
2020-04-17 23:17:47 +00:00
Reference * ref = static_cast < Reference * > ( item - > child ( 0 ) ) ;
2019-04-05 15:12:59 +00:00
item - > removeChild ( 0 ) ;
2020-04-17 23:17:47 +00:00
Contact * cont = static_cast < Contact * > ( ref - > dereference ( ) ) ;
if ( cont - > referencesCount ( ) = = 1 ) {
toInsert . push_back ( ref ) ;
2019-04-05 15:12:59 +00:00
} else {
2020-04-17 23:17:47 +00:00
delete ref ;
2019-04-05 15:12:59 +00:00
}
}
if ( toInsert . size ( ) > 0 ) {
Account * acc = accounts . find ( " account " ) - > second ;
2019-11-17 10:24:12 +00:00
for ( std : : deque < Contact * > : : size_type i = 0 ; i < toInsert . size ( ) ; + + i ) {
2020-04-17 23:17:47 +00:00
acc - > appendChild ( toInsert [ i ] ) ; //TODO optimisation
2019-04-05 15:12:59 +00:00
}
}
2019-06-15 15:29:15 +00:00
item - > deleteLater ( ) ;
groups . erase ( gItr ) ;
2019-04-03 21:23:51 +00:00
}
2019-04-02 21:58:43 +00:00
2019-04-07 20:14:15 +00:00
void Models : : Roster : : changeContact ( const QString & account , const QString & jid , const QMap < QString , QVariant > & data )
2019-04-06 10:14:32 +00:00
{
2021-04-18 12:49:20 +00:00
Element * el = getElement ( { account , jid } ) ;
if ( el ! = NULL ) {
2019-04-07 20:14:15 +00:00
for ( QMap < QString , QVariant > : : const_iterator itr = data . begin ( ) , end = data . end ( ) ; itr ! = end ; + + itr ) {
2021-04-18 12:49:20 +00:00
el - > update ( itr . key ( ) , itr . value ( ) ) ;
2020-02-08 11:44:15 +00:00
}
}
}
void Models : : Roster : : changeMessage ( const QString & account , const QString & jid , const QString & id , const QMap < QString , QVariant > & data )
{
2021-04-18 12:49:20 +00:00
Element * el = getElement ( { account , jid } ) ;
if ( el ! = NULL ) {
el - > changeMessage ( id , data ) ;
2022-03-27 19:05:31 +00:00
} else {
qDebug ( ) < < " A request to change a message of the contact " < < jid < < " in the account " < < account < < " but it wasn't found " ;
2019-08-21 09:35:07 +00:00
}
2019-04-06 10:14:32 +00:00
}
void Models : : Roster : : removeContact ( const QString & account , const QString & jid )
{
ElId id ( account , jid ) ;
2020-04-17 23:17:47 +00:00
std : : map < ElId , Contact * > : : iterator itr = contacts . find ( id ) ;
if ( itr ! = contacts . end ( ) ) {
Contact * contact = itr - > second ;
contacts . erase ( itr ) ;
delete contact ;
std : : set < ElId > toRemove ;
for ( std : : pair < ElId , Group * > pair : groups ) {
if ( pair . second - > childCount ( ) = = 0 ) {
toRemove . insert ( pair . first ) ;
}
2019-04-06 10:14:32 +00:00
}
2019-04-07 14:02:41 +00:00
2020-04-17 23:17:47 +00:00
for ( const ElId & elId : toRemove ) {
removeGroup ( elId . account , elId . name ) ;
}
} else {
qDebug ( ) < < " An attempt to remove contact " < < jid < < " from account " < < account < < " which doesn't exist there, skipping " ;
2019-04-06 10:14:32 +00:00
}
}
void Models : : Roster : : removeContact ( const QString & account , const QString & jid , const QString & group )
{
ElId contactId ( account , jid ) ;
ElId groupId ( account , group ) ;
2020-04-17 23:17:47 +00:00
std : : map < ElId , Contact * > : : iterator cItr = contacts . find ( contactId ) ;
if ( cItr = = contacts . end ( ) ) {
qDebug ( ) < < " An attempt to remove non existing contact " < < jid < < " from group " < < group < < " of account " < < account < < " , skipping " ;
return ;
}
2019-06-22 20:37:22 +00:00
std : : map < ElId , Group * > : : iterator gItr = groups . find ( groupId ) ;
2019-04-06 10:14:32 +00:00
if ( gItr = = groups . end ( ) ) {
qDebug ( ) < < " An attempt to remove contact " < < jid < < " from non existing group " < < group < < " of account " < < account < < " , skipping " ;
return ;
}
2019-09-28 14:30:16 +00:00
Account * acc = accounts . find ( account ) - > second ; //I assume the account is found, otherwise there will be no groups with that ElId;
2019-06-22 20:37:22 +00:00
Group * gr = gItr - > second ;
2020-04-17 23:17:47 +00:00
Contact * cont = cItr - > second ;
int contRow = gr - > getContact ( jid ) ;
if ( contRow = = - 1 ) {
qDebug ( ) < < " An attempt to remove contact " < < jid < < " of account " < < account < < " from group " < < group < < " , but there is no such contact in that group, skipping " ;
return ;
2019-04-06 10:14:32 +00:00
}
2020-04-17 23:17:47 +00:00
Reference * ref = static_cast < Reference * > ( gr - > child ( contRow ) ) ;
gr - > removeChild ( contRow ) ;
2019-04-06 10:14:32 +00:00
2020-04-17 23:17:47 +00:00
if ( cont - > referencesCount ( ) = = 1 ) {
2019-09-28 14:30:16 +00:00
qDebug ( ) < < " An attempt to remove last instance of contact " < < jid < < " from the group " < < group < < " , contact will be moved to ungrouped contacts of " < < account ;
2020-04-17 23:17:47 +00:00
acc - > appendChild ( ref ) ;
2019-09-28 14:30:16 +00:00
} else {
2020-04-17 23:17:47 +00:00
delete ref ;
}
if ( gr - > childCount ( ) = = 0 ) {
removeGroup ( account , group ) ;
2019-04-06 10:14:32 +00:00
}
}
2019-04-07 14:02:41 +00:00
void Models : : Roster : : onChildChanged ( Models : : Item * item , int row , int col )
{
2019-04-07 20:14:15 +00:00
QModelIndex index = createIndex ( row , 0 , item ) ;
2019-10-24 09:42:38 +00:00
QModelIndex index2 = createIndex ( row , 1 , item ) ;
emit dataChanged ( index , index2 ) ;
2019-04-07 14:02:41 +00:00
}
void Models : : Roster : : onChildIsAboutToBeInserted ( Models : : Item * parent , int first , int last )
{
int row = 0 ;
if ( parent ! = root ) {
row = parent - > row ( ) ;
beginInsertRows ( createIndex ( row , 0 , parent ) , first , last ) ;
} else {
beginInsertRows ( QModelIndex ( ) , first , last ) ;
}
}
void Models : : Roster : : onChildIsAboutToBeMoved ( Models : : Item * source , int first , int last , Models : : Item * destination , int newIndex )
{
int oldRow = 0 ;
if ( source ! = root ) {
oldRow = source - > row ( ) ;
}
int newRow = 0 ;
if ( destination ! = root ) {
newRow = destination - > row ( ) ;
}
beginMoveRows ( createIndex ( oldRow , 0 , source ) , first , last , createIndex ( newRow , 0 , destination ) , newIndex ) ;
}
void Models : : Roster : : onChildIsAboutToBeRemoved ( Models : : Item * parent , int first , int last )
{
int row = 0 ;
if ( parent ! = root ) {
row = parent - > row ( ) ;
}
beginRemoveRows ( createIndex ( row , 0 , parent ) , first , last ) ;
}
void Models : : Roster : : onChildInserted ( )
{
endInsertRows ( ) ;
}
void Models : : Roster : : onChildMoved ( )
{
endMoveRows ( ) ;
}
void Models : : Roster : : onChildRemoved ( )
{
endRemoveRows ( ) ;
}
void Models : : Roster : : addPresence ( const QString & account , const QString & jid , const QString & name , const QMap < QString , QVariant > & data )
{
ElId contactId ( account , jid ) ;
2020-04-17 23:17:47 +00:00
std : : map < ElId , Contact * > : : iterator itr = contacts . find ( contactId ) ;
if ( itr ! = contacts . end ( ) ) {
itr - > second - > addPresence ( name , data ) ;
2019-04-07 14:02:41 +00:00
}
}
void Models : : Roster : : removePresence ( const QString & account , const QString & jid , const QString & name )
{
ElId contactId ( account , jid ) ;
2020-04-17 23:17:47 +00:00
std : : map < ElId , Contact * > : : iterator itr = contacts . find ( contactId ) ;
if ( itr ! = contacts . end ( ) ) {
itr - > second - > removePresence ( name ) ;
2019-04-07 14:02:41 +00:00
}
}
2019-04-09 22:01:25 +00:00
2019-04-11 14:58:59 +00:00
void Models : : Roster : : addMessage ( const QString & account , const Shared : : Message & data )
2019-04-09 22:01:25 +00:00
{
2021-04-18 12:49:20 +00:00
Element * el = getElement ( { account , data . getPenPalJid ( ) } ) ;
if ( el ! = NULL ) {
el - > addMessage ( data ) ;
2019-08-31 20:50:05 +00:00
}
2019-04-09 22:01:25 +00:00
}
2019-05-29 15:05:54 +00:00
void Models : : Roster : : removeAccount ( const QString & account )
{
std : : map < QString , Account * > : : const_iterator itr = accounts . find ( account ) ;
if ( itr = = accounts . end ( ) ) {
qDebug ( ) < < " An attempt to remove non existing account " < < account < < " , skipping " ;
return ;
}
Account * acc = itr - > second ;
int index = acc - > row ( ) ;
root - > removeChild ( index ) ;
accountsModel - > removeAccount ( index ) ;
2019-05-30 09:36:21 +00:00
accounts . erase ( itr ) ;
2019-05-29 15:05:54 +00:00
2020-04-17 23:17:47 +00:00
std : : map < ElId , Contact * > : : const_iterator cItr = contacts . begin ( ) ;
2019-05-29 15:05:54 +00:00
while ( cItr ! = contacts . end ( ) ) {
if ( cItr - > first . account = = account ) {
2020-04-17 23:17:47 +00:00
std : : map < ElId , Contact * > : : const_iterator lItr = cItr ;
2019-05-29 15:05:54 +00:00
+ + cItr ;
contacts . erase ( lItr ) ;
} else {
+ + cItr ;
}
}
2019-06-22 20:37:22 +00:00
std : : map < ElId , Group * > : : const_iterator gItr = groups . begin ( ) ;
2019-05-29 15:05:54 +00:00
while ( gItr ! = groups . end ( ) ) {
if ( gItr - > first . account = = account ) {
2019-06-22 20:37:22 +00:00
std : : map < ElId , Group * > : : const_iterator lItr = gItr ;
2019-05-29 15:05:54 +00:00
+ + gItr ;
groups . erase ( lItr ) ;
} else {
+ + gItr ;
}
}
2019-07-11 08:51:52 +00:00
std : : map < ElId , Room * > : : const_iterator rItr = rooms . begin ( ) ;
while ( rItr ! = rooms . end ( ) ) {
if ( rItr - > first . account = = account ) {
std : : map < ElId , Room * > : : const_iterator lItr = rItr ;
+ + rItr ;
rooms . erase ( lItr ) ;
} else {
+ + rItr ;
}
}
2021-05-16 21:52:59 +00:00
disconnect ( acc , & Account : : reconnected , this , & Roster : : onAccountReconnected ) ;
2019-05-30 09:36:21 +00:00
acc - > deleteLater ( ) ;
2019-05-29 15:05:54 +00:00
}
2019-06-18 15:08:03 +00:00
2022-04-18 16:54:42 +00:00
QString Models : : Roster : : getContactName ( const QString & account , const QString & jid ) const
2019-06-18 15:08:03 +00:00
{
2019-08-31 20:50:05 +00:00
ElId id ( account , jid ) ;
2020-04-17 23:17:47 +00:00
std : : map < ElId , Contact * > : : const_iterator cItr = contacts . find ( id ) ;
2019-08-31 20:50:05 +00:00
QString name = " " ;
2019-06-18 15:08:03 +00:00
if ( cItr = = contacts . end ( ) ) {
2019-08-31 20:50:05 +00:00
std : : map < ElId , Room * > : : const_iterator rItr = rooms . find ( id ) ;
if ( rItr = = rooms . end ( ) ) {
qDebug ( ) < < " An attempt to get a name of non existing contact/room " < < account < < " : " < < jid < < " , skipping " ;
} else {
2019-09-24 09:21:29 +00:00
name = rItr - > second - > getRoomName ( ) ;
2019-08-31 20:50:05 +00:00
}
} else {
name = cItr - > second - > getContactName ( ) ;
2019-06-18 15:08:03 +00:00
}
2019-08-31 20:50:05 +00:00
return name ;
2019-06-18 15:08:03 +00:00
}
2019-07-11 08:51:52 +00:00
void Models : : Roster : : addRoom ( const QString & account , const QString jid , const QMap < QString , QVariant > & data )
{
Account * acc ;
{
std : : map < QString , Account * > : : iterator itr = accounts . find ( account ) ;
if ( itr = = accounts . end ( ) ) {
qDebug ( ) < < " An attempt to add a room " < < jid < < " to non existing account " < < account < < " , skipping " ;
return ;
}
acc = itr - > second ;
}
ElId id = { account , jid } ;
std : : map < ElId , Room * > : : const_iterator itr = rooms . find ( id ) ;
if ( itr ! = rooms . end ( ) ) {
qDebug ( ) < < " An attempt to add already existing room " < < jid < < " , skipping " ;
return ;
}
2020-08-11 22:49:51 +00:00
Room * room = new Room ( acc , jid , data ) ;
2022-04-19 17:24:41 +00:00
connect ( room , & Room : : requestArchive , this , & Roster : : onElementRequestArchive ) ;
connect ( room , & Room : : fileDownloadRequest , this , & Roster : : fileDownloadRequest ) ;
connect ( room , & Room : : unnoticedMessage , this , & Roster : : unnoticedMessage ) ;
connect ( room , & Room : : localPathInvalid , this , & Roster : : localPathInvalid ) ;
2019-07-11 08:51:52 +00:00
rooms . insert ( std : : make_pair ( id , room ) ) ;
acc - > appendChild ( room ) ;
}
void Models : : Roster : : changeRoom ( const QString & account , const QString jid , const QMap < QString , QVariant > & data )
{
ElId id = { account , jid } ;
std : : map < ElId , Room * > : : const_iterator itr = rooms . find ( id ) ;
if ( itr = = rooms . end ( ) ) {
qDebug ( ) < < " An attempt to change non existing room " < < jid < < " , skipping " ;
return ;
}
Room * room = itr - > second ;
for ( QMap < QString , QVariant > : : const_iterator dItr = data . begin ( ) , dEnd = data . end ( ) ; dItr ! = dEnd ; + + dItr ) {
room - > update ( dItr . key ( ) , dItr . value ( ) ) ;
}
}
void Models : : Roster : : removeRoom ( const QString & account , const QString jid )
{
Account * acc ;
{
std : : map < QString , Account * > : : iterator itr = accounts . find ( account ) ;
if ( itr = = accounts . end ( ) ) {
qDebug ( ) < < " An attempt to remove a room " < < jid < < " from non existing account " < < account < < " , skipping " ;
return ;
}
acc = itr - > second ;
}
ElId id = { account , jid } ;
std : : map < ElId , Room * > : : const_iterator itr = rooms . find ( id ) ;
if ( itr = = rooms . end ( ) ) {
qDebug ( ) < < " An attempt to remove non existing room " < < jid < < " , skipping " ;
return ;
}
Room * room = itr - > second ;
acc - > removeChild ( room - > row ( ) ) ;
room - > deleteLater ( ) ;
rooms . erase ( itr ) ;
}
2019-09-02 11:17:28 +00:00
void Models : : Roster : : addRoomParticipant ( const QString & account , const QString & jid , const QString & name , const QMap < QString , QVariant > & data )
{
ElId id = { account , jid } ;
std : : map < ElId , Room * > : : const_iterator itr = rooms . find ( id ) ;
if ( itr = = rooms . end ( ) ) {
qDebug ( ) < < " An attempt to add participant " < < name < < " non existing room " < < jid < < " of an account " < < account < < " , skipping " ;
return ;
} else {
itr - > second - > addParticipant ( name , data ) ;
}
}
void Models : : Roster : : changeRoomParticipant ( const QString & account , const QString & jid , const QString & name , const QMap < QString , QVariant > & data )
{
ElId id = { account , jid } ;
std : : map < ElId , Room * > : : const_iterator itr = rooms . find ( id ) ;
if ( itr = = rooms . end ( ) ) {
qDebug ( ) < < " An attempt change participant " < < name < < " of non existing room " < < jid < < " of an account " < < account < < " , skipping " ;
return ;
} else {
itr - > second - > changeParticipant ( name , data ) ;
}
}
void Models : : Roster : : removeRoomParticipant ( const QString & account , const QString & jid , const QString & name )
{
ElId id = { account , jid } ;
std : : map < ElId , Room * > : : const_iterator itr = rooms . find ( id ) ;
if ( itr = = rooms . end ( ) ) {
qDebug ( ) < < " An attempt remove participant " < < name < < " from non existing room " < < jid < < " of an account " < < account < < " , skipping " ;
return ;
} else {
itr - > second - > removeParticipant ( name ) ;
}
}
2019-09-28 14:30:16 +00:00
std : : deque < QString > Models : : Roster : : groupList ( const QString & account ) const
{
std : : deque < QString > answer ;
for ( std : : pair < ElId , Group * > pair : groups ) {
if ( pair . first . account = = account ) {
answer . push_back ( pair . first . name ) ;
}
}
return answer ;
}
bool Models : : Roster : : groupHasContact ( const QString & account , const QString & group , const QString & contact ) const
{
ElId grId ( { account , group } ) ;
std : : map < ElId , Group * > : : const_iterator gItr = groups . find ( grId ) ;
if ( gItr = = groups . end ( ) ) {
return false ;
} else {
2020-04-17 23:17:47 +00:00
return gItr - > second - > getContact ( contact ) ! = - 1 ;
2019-09-28 14:30:16 +00:00
}
}
2019-10-25 13:38:48 +00:00
2022-04-18 16:54:42 +00:00
QString Models : : Roster : : getContactIconPath ( const QString & account , const QString & jid , const QString & resource ) const
2019-10-25 13:38:48 +00:00
{
ElId id ( account , jid ) ;
2020-04-17 23:17:47 +00:00
std : : map < ElId , Contact * > : : const_iterator cItr = contacts . find ( id ) ;
2019-10-25 13:38:48 +00:00
QString path = " " ;
if ( cItr = = contacts . end ( ) ) {
std : : map < ElId , Room * > : : const_iterator rItr = rooms . find ( id ) ;
if ( rItr = = rooms . end ( ) ) {
qDebug ( ) < < " An attempt to get an icon path of non existing contact " < < account < < " : " < < jid < < " , returning empty value " ;
} else {
2019-12-31 18:14:12 +00:00
path = rItr - > second - > getParticipantIconPath ( resource ) ;
2019-10-25 13:38:48 +00:00
}
} else {
if ( cItr - > second - > getAvatarState ( ) ! = Shared : : Avatar : : empty ) {
path = cItr - > second - > getAvatarPath ( ) ;
}
}
return path ;
}
2019-12-20 15:41:20 +00:00
Models : : Account * Models : : Roster : : getAccount ( const QString & name )
{
return accounts . find ( name ) - > second ;
}
2019-12-25 10:24:20 +00:00
QModelIndex Models : : Roster : : getAccountIndex ( const QString & name )
{
std : : map < QString , Account * > : : const_iterator itr = accounts . find ( name ) ;
if ( itr = = accounts . end ( ) ) {
return QModelIndex ( ) ;
} else {
return index ( itr - > second - > row ( ) , 0 , QModelIndex ( ) ) ;
}
}
QModelIndex Models : : Roster : : getGroupIndex ( const QString & account , const QString & name )
{
std : : map < QString , Account * > : : const_iterator itr = accounts . find ( account ) ;
if ( itr = = accounts . end ( ) ) {
return QModelIndex ( ) ;
} else {
std : : map < ElId , Group * > : : const_iterator gItr = groups . find ( { account , name } ) ;
if ( gItr = = groups . end ( ) ) {
return QModelIndex ( ) ;
} else {
QModelIndex accIndex = index ( itr - > second - > row ( ) , 0 , QModelIndex ( ) ) ;
return index ( gItr - > second - > row ( ) , 0 , accIndex ) ;
}
}
}
2020-08-11 22:49:51 +00:00
void Models : : Roster : : onElementRequestArchive ( const QString & before )
{
Element * el = static_cast < Element * > ( sender ( ) ) ;
emit requestArchive ( el - > getAccountName ( ) , el - > getJid ( ) , before ) ;
}
2020-08-21 20:57:48 +00:00
void Models : : Roster : : responseArchive ( const QString & account , const QString & jid , const std : : list < Shared : : Message > & list , bool last )
2020-08-11 22:49:51 +00:00
{
ElId id ( account , jid ) ;
2021-04-18 12:49:20 +00:00
Element * el = getElement ( id ) ;
if ( el ! = NULL ) {
el - > responseArchive ( list , last ) ;
}
}
void Models : : Roster : : fileProgress ( const std : : list < Shared : : MessageInfo > & msgs , qreal value , bool up )
{
for ( const Shared : : MessageInfo & info : msgs ) {
Element * el = getElement ( { info . account , info . jid } ) ;
if ( el ! = NULL ) {
el - > fileProgress ( info . messageId , value , up ) ;
2020-08-11 22:49:51 +00:00
}
}
}
2021-02-27 12:21:27 +00:00
2021-04-18 12:49:20 +00:00
void Models : : Roster : : fileComplete ( const std : : list < Shared : : MessageInfo > & msgs , bool up )
2021-02-27 12:21:27 +00:00
{
2021-04-18 12:49:20 +00:00
for ( const Shared : : MessageInfo & info : msgs ) {
Element * el = getElement ( { info . account , info . jid } ) ;
if ( el ! = NULL ) {
el - > fileComplete ( info . messageId , up ) ;
}
2021-02-27 12:21:27 +00:00
}
2021-04-18 12:49:20 +00:00
}
void Models : : Roster : : fileError ( const std : : list < Shared : : MessageInfo > & msgs , const QString & err , bool up )
{
for ( const Shared : : MessageInfo & info : msgs ) {
Element * el = getElement ( { info . account , info . jid } ) ;
if ( el ! = NULL ) {
el - > fileError ( info . messageId , err , up ) ;
}
2021-02-27 12:21:27 +00:00
}
}
2021-04-18 12:49:20 +00:00
Models : : Element * Models : : Roster : : getElement ( const Models : : Roster : : ElId & id )
2021-02-27 12:21:27 +00:00
{
2021-04-18 12:49:20 +00:00
std : : map < ElId , Contact * > : : iterator cItr = contacts . find ( id ) ;
if ( cItr ! = contacts . end ( ) ) {
return cItr - > second ;
2021-02-27 12:21:27 +00:00
} else {
2021-04-18 12:49:20 +00:00
std : : map < ElId , Room * > : : iterator rItr = rooms . find ( id ) ;
if ( rItr ! = rooms . end ( ) ) {
return rItr - > second ;
2021-02-27 12:21:27 +00:00
}
}
2021-04-18 12:49:20 +00:00
return NULL ;
2021-02-27 12:21:27 +00:00
}
2021-05-16 21:52:59 +00:00
void Models : : Roster : : onAccountReconnected ( )
{
Account * acc = static_cast < Account * > ( sender ( ) ) ;
QString accName = acc - > getName ( ) ;
for ( const std : : pair < const ElId , Contact * > & pair : contacts ) {
if ( pair . first . account = = accName ) {
pair . second - > handleRecconnect ( ) ;
}
}
}