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
using namespace Models ;
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 ( ) ,
2019-04-05 15:12:59 +00:00
contacts ( )
2019-03-31 21:05:09 +00:00
{
2019-04-03 18:15:36 +00:00
connect ( accountsModel ,
SIGNAL ( dataChanged ( const QModelIndex & , const QModelIndex & , const QVector < int > & ) ) ,
this ,
SLOT ( onAccountDataChanged ( const QModelIndex & , const QModelIndex & , const QVector < int > & ) ) ) ;
2019-04-09 15:04:08 +00:00
connect ( root , SIGNAL ( childChanged ( Models : : Item * , int , int ) ) , this , SLOT ( onChildChanged ( Models : : Item * , int , int ) ) ) ;
2019-04-07 14:02:41 +00:00
connect ( root , SIGNAL ( childIsAboutToBeInserted ( Item * , int , int ) ) , this , SLOT ( onChildIsAboutToBeInserted ( Item * , int , int ) ) ) ;
connect ( root , SIGNAL ( childInserted ( ) ) , this , SLOT ( onChildInserted ( ) ) ) ;
connect ( root , SIGNAL ( childIsAboutToBeRemoved ( Item * , int , int ) ) , this , SLOT ( onChildIsAboutToBeRemoved ( Item * , int , int ) ) ) ;
connect ( root , SIGNAL ( childRemoved ( ) ) , this , SLOT ( onChildRemoved ( ) ) ) ;
connect ( root , SIGNAL ( childIsAboutToBeMoved ( Item * , int , int , Item * , int ) ) , this , SLOT ( onChildIsAboutToBeMoved ( Item * , int , int , Item * , int ) ) ) ;
connect ( root , SIGNAL ( childMoved ( ) ) , this , SLOT ( 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 ) ;
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 ( ) ) ;
2019-03-31 21:05:09 +00:00
switch ( role ) {
case Qt : : DisplayRole :
{
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 ) {
str + = QString ( " ( " ) + " New messages " + " ) " ;
}
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-04-03 18:15:36 +00:00
Account * acc = static_cast < Account * > ( item ) ;
2019-06-23 21:09:39 +00:00
result = acc - > getStatusIcon ( false ) ;
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-06-23 21:09:39 +00:00
result = contact - > getStatusIcon ( false ) ;
2019-04-07 14:02:41 +00:00
}
break ;
2019-07-11 08:51:52 +00:00
case Item : : presence : {
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 : {
Room * room = static_cast < Room * > ( item ) ;
result = room - > getStatusIcon ( false ) ;
}
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 ) ;
2019-06-22 20:37:22 +00:00
result = QString ( Shared : : availabilityNames [ 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 ) {
str + = QString ( " New messages: " ) + std : : to_string ( mc ) . c_str ( ) + " \n " ;
}
Shared : : SubscriptionState ss = contact - > getState ( ) ;
if ( ss = = Shared : : both ) {
Shared : : Availability av = contact - > getAvailability ( ) ;
str + = " Availability: " + Shared : : availabilityNames [ av ] ;
if ( av ! = Shared : : offline ) {
QString s = contact - > getStatus ( ) ;
if ( s . size ( ) > 0 ) {
str + = " \n Status: " + s ;
}
}
str + = " \n Subscription: " + Shared : : subscriptionStateNames [ ss ] ;
} else {
str + = " Subscription: " + Shared : : subscriptionStateNames [ ss ] ;
}
result = str ;
}
break ;
case Item : : presence : {
Presence * contact = static_cast < Presence * > ( 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 ) {
str + = QString ( " New messages: " ) + std : : to_string ( mc ) . c_str ( ) + " \n " ;
}
Shared : : Availability av = contact - > getAvailability ( ) ;
str + = " Availability: " + Shared : : availabilityNames [ av ] ;
QString s = contact - > getStatus ( ) ;
if ( s . size ( ) > 0 ) {
str + = " \n Status: " + s ;
}
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 ) {
str + = QString ( " New messages: " ) + std : : to_string ( count ) . c_str ( ) + " \n " ;
}
str + = QString ( " Online contacts: " ) + std : : to_string ( gr - > getOnlineContacts ( ) ) . c_str ( ) + " \n " ;
str + = QString ( " 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 ) ;
unsigned int count = rm - > getUnreadMessagesCount ( ) ;
QString str ( " " ) ;
if ( count > 0 ) {
str + = QString ( " New messages: " ) + std : : to_string ( count ) . c_str ( ) + " \n " ;
}
2019-08-28 11:40:55 +00:00
str + = QString ( " Subscription: " ) + rm - > getStatusText ( ) ;
2019-07-11 08:51:52 +00:00
result = str ;
}
break ;
2019-06-21 19:33:38 +00:00
default :
result = " " ;
break ;
}
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 ( ) ) {
return 0 ;
}
return QAbstractItemModel : : flags ( index ) ;
}
int Models : : Roster : : rowCount ( const QModelIndex & parent ) const
{
Item * parentItem ;
if ( parent . column ( ) > 0 ) {
return 0 ;
}
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
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 ( t l , 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 ;
Contact * contact ;
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-04-07 20:14:15 +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 ;
}
if ( group = = " " ) {
std : : multimap < ElId , Contact * > : : iterator itr = contacts . lower_bound ( id ) ;
std : : multimap < ElId , Contact * > : : iterator eItr = contacts . upper_bound ( id ) ;
while ( itr ! = eItr ) {
if ( itr - > second - > parentItem ( ) = = acc ) {
2019-04-07 20:14:15 +00:00
qDebug ( ) < < " An attempt to add a contact " < < jid < < " ungrouped to non the account " < < account < < " for the second time, skipping " ;
2019-04-05 15:12:59 +00:00
return ;
}
2019-06-15 15:29:15 +00:00
itr + + ;
2019-04-05 15:12:59 +00:00
}
parent = acc ;
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-04-07 20:14:15 +00:00
qDebug ( ) < < " An attempt to add a contact " < < jid < < " to non existing group " < < group < < " , skipping " ;
2019-04-03 21:23:51 +00:00
return ;
}
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
for ( int i = 0 ; i < parent - > childCount ( ) ; + + i ) {
Item * item = parent - > child ( i ) ;
if ( item - > type = = Item : : contact ) {
Contact * ca = static_cast < Contact * > ( item ) ;
if ( ca - > getJid ( ) = = jid ) {
2019-04-07 20:14:15 +00:00
qDebug ( ) < < " An attempt to add a contact " < < jid < < " to the group " < < group < < " for the second time, skipping " ;
2019-04-05 15:12:59 +00:00
return ;
}
}
}
for ( int i = 0 ; i < acc - > childCount ( ) ; + + i ) {
Item * item = acc - > child ( i ) ;
if ( item - > type = = Item : : contact ) {
Contact * ca = static_cast < Contact * > ( item ) ;
if ( ca - > getJid ( ) = = jid ) {
2019-04-07 20:14:15 +00:00
qDebug ( ) < < " An attempt to add a already existing contact " < < jid < < " to the group " < < group < < " , contact will be moved from ungrouped contacts of " < < account ;
2019-04-05 15:12:59 +00:00
parent - > appendChild ( ca ) ;
return ;
}
}
}
2019-04-03 21:23:51 +00:00
}
2019-04-07 20:14:15 +00:00
contact = new Contact ( jid , data ) ;
2019-04-05 15:12:59 +00:00
contacts . insert ( std : : make_pair ( id , contact ) ) ;
2019-07-11 08:51:52 +00:00
parent - > appendChild ( contact ) ;
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 ) ;
std : : deque < Contact * > toInsert ;
for ( int i = 0 ; item - > childCount ( ) > 0 ; + + i ) {
Contact * cont = static_cast < Contact * > ( item - > child ( 0 ) ) ;
item - > removeChild ( 0 ) ;
std : : multimap < ElId , Contact * > : : iterator cBeg = contacts . lower_bound ( { account , cont - > getJid ( ) } ) ;
std : : multimap < ElId , Contact * > : : iterator cEnd = contacts . upper_bound ( { account , cont - > getJid ( ) } ) ;
int count = std : : distance ( cBeg , cEnd ) ;
if ( count > 1 ) {
for ( ; cBeg ! = cEnd ; + + count , + + cBeg ) {
if ( cBeg - > second = = cont ) {
delete cont ;
contacts . erase ( cBeg ) ;
break ;
}
}
} else {
toInsert . push_back ( cont ) ;
}
}
if ( toInsert . size ( ) > 0 ) {
Account * acc = accounts . find ( " account " ) - > second ;
for ( int i = 0 ; i < toInsert . size ( ) ; + + i ) {
Contact * cont = toInsert [ i ] ;
2019-04-07 14:02:41 +00:00
acc - > appendChild ( cont ) ; //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
{
ElId id ( account , jid ) ;
std : : multimap < ElId , Contact * > : : iterator cBeg = contacts . lower_bound ( id ) ;
std : : multimap < ElId , Contact * > : : iterator cEnd = contacts . upper_bound ( id ) ;
for ( ; cBeg ! = cEnd ; + + cBeg ) {
2019-04-07 20:14:15 +00:00
for ( QMap < QString , QVariant > : : const_iterator itr = data . begin ( ) , end = data . end ( ) ; itr ! = end ; + + itr ) {
cBeg - > second - > update ( itr . key ( ) , itr . value ( ) ) ; ;
}
2019-04-06 10:14:32 +00:00
}
2019-08-21 09:35:07 +00:00
std : : map < ElId , Room * > : : iterator rItr = rooms . find ( id ) ;
if ( rItr ! = rooms . end ( ) ) {
for ( QMap < QString , QVariant > : : const_iterator itr = data . begin ( ) , end = data . end ( ) ; itr ! = end ; + + itr ) {
rItr - > second - > update ( itr . key ( ) , itr . value ( ) ) ; ;
}
}
2019-04-06 10:14:32 +00:00
}
void Models : : Roster : : removeContact ( const QString & account , const QString & jid )
{
ElId id ( account , jid ) ;
std : : multimap < ElId , Contact * > : : iterator cBeg = contacts . lower_bound ( id ) ;
std : : multimap < ElId , Contact * > : : iterator cEnd = contacts . upper_bound ( id ) ;
2019-06-15 15:29:15 +00:00
std : : multimap < ElId , Contact * > : : iterator cpBeg = cBeg ;
2019-04-06 10:14:32 +00:00
QSet < QString > toRemove ;
for ( ; cBeg ! = cEnd ; + + cBeg ) {
Contact * contact = cBeg - > second ;
Item * parent = contact - > parentItem ( ) ;
if ( parent - > type = = Item : : group & & parent - > childCount ( ) = = 1 ) {
toRemove . insert ( parent - > getName ( ) ) ;
}
2019-04-07 14:02:41 +00:00
parent - > removeChild ( contact - > row ( ) ) ;
2019-06-15 15:29:15 +00:00
contact - > deleteLater ( ) ;
2019-04-06 10:14:32 +00:00
}
2019-06-15 15:29:15 +00:00
contacts . erase ( cpBeg , cEnd ) ;
2019-04-06 10:14:32 +00:00
for ( QSet < QString > : : const_iterator itr = toRemove . begin ( ) , end = toRemove . end ( ) ; itr ! = end ; + + itr ) {
removeGroup ( account , * itr ) ;
}
}
void Models : : Roster : : removeContact ( const QString & account , const QString & jid , const QString & group )
{
ElId contactId ( account , jid ) ;
ElId groupId ( account , group ) ;
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-06-22 20:37:22 +00:00
Group * gr = gItr - > second ;
2019-04-06 10:14:32 +00:00
Contact * cont = 0 ;
std : : multimap < ElId , Contact * > : : iterator cBeg = contacts . lower_bound ( contactId ) ;
std : : multimap < ElId , Contact * > : : iterator cEnd = contacts . upper_bound ( contactId ) ;
for ( ; cBeg ! = cEnd ; + + cBeg ) {
if ( cBeg - > second - > parentItem ( ) = = gr ) {
cont = cBeg - > second ;
2019-06-15 15:29:15 +00:00
contacts . erase ( cBeg ) ;
2019-04-06 10:14:32 +00:00
break ;
}
}
if ( cont = = 0 ) {
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-07 14:02:41 +00:00
gr - > removeChild ( cont - > row ( ) ) ;
2019-06-15 15:29:15 +00:00
cont - > deleteLater ( ) ;
2019-04-06 10:14:32 +00:00
if ( gr - > childCount ( ) = = 0 ) {
removeGroup ( account , group ) ;
}
}
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-04-07 14:02:41 +00:00
emit dataChanged ( index , index ) ;
}
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 ) ;
std : : multimap < ElId , Contact * > : : iterator cBeg = contacts . lower_bound ( contactId ) ;
std : : multimap < ElId , Contact * > : : iterator cEnd = contacts . upper_bound ( contactId ) ;
for ( ; cBeg ! = cEnd ; + + cBeg ) {
cBeg - > second - > addPresence ( name , data ) ;
}
}
void Models : : Roster : : removePresence ( const QString & account , const QString & jid , const QString & name )
{
ElId contactId ( account , jid ) ;
std : : multimap < ElId , Contact * > : : iterator cBeg = contacts . lower_bound ( contactId ) ;
std : : multimap < ElId , Contact * > : : iterator cEnd = contacts . upper_bound ( contactId ) ;
for ( ; cBeg ! = cEnd ; + + cBeg ) {
cBeg - > second - > removePresence ( name ) ;
}
}
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
{
2019-04-11 14:58:59 +00:00
ElId id ( account , data . getPenPalJid ( ) ) ;
2019-04-09 22:01:25 +00:00
std : : multimap < ElId , Contact * > : : iterator cBeg = contacts . lower_bound ( id ) ;
std : : multimap < ElId , Contact * > : : iterator cEnd = contacts . upper_bound ( id ) ;
for ( ; cBeg ! = cEnd ; + + cBeg ) {
cBeg - > second - > addMessage ( data ) ;
}
}
void Models : : Roster : : dropMessages ( const QString & account , const QString & jid )
{
ElId id ( account , jid ) ;
for ( std : : multimap < ElId , Contact * > : : iterator cBeg = contacts . lower_bound ( id ) , cEnd = contacts . upper_bound ( id ) ; cBeg ! = cEnd ; + + cBeg ) {
cBeg - > second - > dropMessages ( ) ;
}
}
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
std : : multimap < ElId , Contact * > : : const_iterator cItr = contacts . begin ( ) ;
while ( cItr ! = contacts . end ( ) ) {
if ( cItr - > first . account = = account ) {
std : : multimap < ElId , Contact * > : : const_iterator lItr = cItr ;
+ + 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 ;
}
}
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
QString Models : : Roster : : getContactName ( const QString & account , const QString & jid )
{
std : : multimap < ElId , Contact * > : : const_iterator cItr = contacts . find ( { account , jid } ) ;
if ( cItr = = contacts . end ( ) ) {
qDebug ( ) < < " An attempt to get a name of non existing contact " < < account < < " : " < < jid < < " , skipping " ;
return " " ;
}
return cItr - > second - > getContactName ( ) ;
}
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 ;
}
Room * room = new Room ( jid , data ) ;
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 ) ;
}