• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdenetwork API Reference
  • KDE Home
  • Contact Us
 

kopete/kopete

  • sources
  • kde-4.14
  • kdenetwork
  • kopete
  • kopete
  • contactlist
contactlisttreemodel.cpp
Go to the documentation of this file.
1 /*
2  Kopete Contactlist Model
3 
4  Copyright (c) 2007 by Aleix Pol <aleixpol@gmail.com>
5  Copyright (c) 2008 by Matt Rogers <mattr@kde.org>
6  Copyright (c) 2009 by Gustavo Pichorim Boiko <gustavo.boiko@kdemail.net>
7  Copyright 2009 by Roman Jarosz <kedgedev@gmail.com>
8 
9  Kopete (c) 2002-2009 by the Kopete developers <kopete-devel@kde.org>
10 
11  *************************************************************************
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * *
18  *************************************************************************
19 */
20 
21 #include "contactlisttreemodel.h"
22 #include "contactlisttreemodel_p.h"
23 
24 #include <QMimeData>
25 #include <QDomDocument>
26 
27 #include <KIcon>
28 #include <KLocale>
29 
30 #include "kopeteaccount.h"
31 #include "kopetegroup.h"
32 #include "kopetemetacontact.h"
33 #include "kopetecontact.h"
34 #include "kopetecontactlist.h"
35 #include "kopeteitembase.h"
36 #include "kopeteappearancesettings.h"
37 
38 namespace Kopete {
39 
40 namespace UI {
41 
42 ContactListTreeModel::ContactListTreeModel( QObject* parent )
43  : ContactListModel( parent )
44 {
45  m_topLevelGroup = new GroupModelItem( Kopete::Group::topLevel() );
46  m_groups.insert( m_topLevelGroup->group(), m_topLevelGroup );
47 }
48 
49 ContactListTreeModel::~ContactListTreeModel()
50 {
51  saveModelSettings( "Tree" );
52 }
53 
54 void ContactListTreeModel::addMetaContact( Kopete::MetaContact* contact )
55 {
56  ContactListModel::addMetaContact( contact );
57 
58  foreach( Kopete::Group* g, contact->groups() )
59  addMetaContactToGroup( contact, g );
60 
61  if ( Kopete::AppearanceSettings::self()->showOfflineGrouped() )
62  {
63  if ( !contact->isOnline() )
64  addMetaContactToGroup( contact, Kopete::Group::offline() );
65  else
66  removeMetaContactFromGroup( contact, Kopete::Group::offline() );
67  }
68 }
69 
70 void ContactListTreeModel::removeMetaContact( Kopete::MetaContact* contact )
71 {
72  ContactListModel::removeMetaContact( contact );
73 
74  foreach(Kopete::Group *g, contact->groups())
75  removeMetaContactFromGroup(contact, g);
76 }
77 
78 void ContactListTreeModel::addGroup( Kopete::Group* group )
79 {
80  if ( group == Kopete::Group::topLevel() )
81  {
82  Q_ASSERT( m_topLevelGroup->group() == group );
83  }
84  else if ( !m_groups.contains( group ) )
85  {
86  kDebug(14001) << "addGroup" << group->displayName();
87 
88  GroupModelItem* gmi = new GroupModelItem( group );
89  m_groups.insert( group, gmi );
90 
91  int pos = m_topLevelGroup->count();
92  beginInsertRows( indexFor( m_topLevelGroup ), pos, pos );
93  m_topLevelGroup->append( gmi );
94  Q_ASSERT( gmi->index() == pos );
95  endInsertRows();
96  }
97 }
98 
99 void ContactListTreeModel::removeGroup( Kopete::Group* group )
100 {
101  Q_ASSERT( group != Kopete::Group::topLevel() );
102 
103  GroupModelItem* gmi = m_groups.value( group );
104  int pos = gmi->index();
105 
106  beginRemoveRows( indexFor( gmi->parent() ), pos, pos );
107  gmi->remove();
108  m_groups.remove( group );
109  endRemoveRows();
110 
111  delete gmi;
112 }
113 
114 void ContactListTreeModel::addMetaContactToGroup( Kopete::MetaContact *mc, Kopete::Group *group )
115 {
116  GroupModelItem* groupModelItem = m_groups.value( group );
117  if ( !groupModelItem )
118  {
119  addGroup( group );
120  groupModelItem = m_groups.value( group );
121  }
122  QModelIndex parent = indexFor( groupModelItem );
123 
124  GroupMetaContactPair groupMetaContactPair( group, mc );
125  int mcDesireIndex = groupModelItem->count();
126 
127  // If we use manual sorting we most likely will have possition where the metaContact should be inserted.
128  if ( m_manualMetaContactSorting )
129  {
130  GroupMetaContactPair groupMetaContactPair( group, mc );
131  if ( m_addContactPosition.contains( groupMetaContactPair ) )
132  {
133  mcDesireIndex = m_addContactPosition.value( groupMetaContactPair );
134  m_addContactPosition.remove( groupMetaContactPair );
135  }
136  }
137 
138  // Check if mcDesireIndex isn't invalid (in group area)
139  int metaContactCount = groupModelItem->metaContactCount();
140  if ( mcDesireIndex < 0 || mcDesireIndex > metaContactCount )
141  mcDesireIndex = metaContactCount;
142 
143  MetaContactModelItem* mcModelItem = m_metaContacts.value( groupMetaContactPair );
144  if ( mcModelItem )
145  {
146  int mcIndex = mcModelItem->index();
147  // If the manual index is the same do nothing otherwise change possition
148  if ( mcIndex == mcDesireIndex )
149  return;
150 
151  // We're moving metaContact so temporary remove it so model is aware of the change.
152  beginRemoveRows( parent, mcIndex, mcIndex );
153  mcModelItem->remove();
154  endRemoveRows();
155 
156  // If mcDesireIndex was after mcIndex decrement it because we have removed metaContact
157  if ( mcIndex < mcDesireIndex )
158  mcDesireIndex--;
159  }
160  else
161  {
162  mcModelItem = new MetaContactModelItem( mc );
163  m_metaContacts.insert( groupMetaContactPair, mcModelItem );
164  }
165 
166  beginInsertRows( parent, mcDesireIndex, mcDesireIndex );
167  groupModelItem->insert( mcDesireIndex, mcModelItem );
168  endInsertRows();
169 
170  // emit the dataChanged signal for the group index so that the filtering proxy
171  // can evaluate the row
172  emit dataChanged( parent, parent );
173 }
174 
175 void ContactListTreeModel::removeMetaContactFromGroup( Kopete::MetaContact *mc, Kopete::Group *group )
176 {
177  GroupMetaContactPair groupMetaContactPair( group, mc );
178  MetaContactModelItem* mcModelItem = m_metaContacts.value( groupMetaContactPair );
179  if ( !mcModelItem )
180  return;
181 
182  int offset = mcModelItem->index();
183  QModelIndex parent = indexFor( mcModelItem->parent() );
184 
185  beginRemoveRows( parent, offset, offset);
186  mcModelItem->remove();
187  m_metaContacts.remove( groupMetaContactPair );
188  endRemoveRows();
189 
190  delete mcModelItem;
191 
192  // emit the dataChanged signal for the group index so that the filtering proxy
193  // can evaluate if the group row should still be visible
194  emit dataChanged( parent, parent );
195 }
196 
197 int ContactListTreeModel::rowCount( const QModelIndex& parent ) const
198 {
199  if ( !parent.isValid() )
200  return 1;
201 
202  return itemFor( parent )->count();
203 }
204 
205 bool ContactListTreeModel::hasChildren( const QModelIndex& parent ) const
206 {
207  if ( !parent.isValid() )
208  return true;
209 
210  return itemFor( parent )->hasChildren();
211 }
212 
213 QModelIndex ContactListTreeModel::index( int row, int column, const QModelIndex & parent ) const
214 {
215  if ( row < 0 || row >= rowCount( parent ) )
216  return QModelIndex();
217 
218  if ( !parent.isValid() )
219  return createIndex( row, column, m_topLevelGroup );
220 
221  GroupModelItem *gmi = dynamic_cast<GroupModelItem*>( itemFor( parent ) );
222  return createIndex( row, column, gmi->at( row ) );
223 }
224 
225 int ContactListTreeModel::countConnected( GroupModelItem* gmi ) const
226 {
227  int onlineCount = 0;
228 
229  QList<ContactListModelItem*> items = gmi->items();
230  foreach ( ContactListModelItem* clmi, items )
231  {
232  MetaContactModelItem* mcmi = dynamic_cast<MetaContactModelItem*>(clmi);
233  if ( mcmi && mcmi->metaContact() && ( mcmi->metaContact()->isOnline() || mcmi->metaContact()->isAlwaysVisible() ) )
234  onlineCount++;
235  }
236 
237  return onlineCount;
238 }
239 
240 bool ContactListTreeModel::setData( const QModelIndex & index, const QVariant & value, int role )
241 {
242  if ( !index.isValid() )
243  return false;
244 
245  ContactListModel::setData(index,value,role);
246 
247  if ( role == Kopete::Items::ExpandStateRole )
248  {
249  ContactListModelItem *clmi = itemFor( index );
250  GroupModelItem *gmi = dynamic_cast<GroupModelItem*>( clmi );
251 
252  if ( gmi && gmi->group() )
253  {
254  if ( gmi->group()->isExpanded() != value.toBool() )
255  {
256  gmi->group()->setExpanded( value.toBool() );
257  emit dataChanged( index, index );
258  }
259  return true;
260  }
261  }
262 
263  return false;
264 }
265 
266 QVariant ContactListTreeModel::data ( const QModelIndex & index, int role ) const
267 {
268  if ( !index.isValid() )
269  return QVariant();
270 
271  using namespace Kopete;
272 
273  /* do all the casting up front. I need to profile to see how expensive this is though */
274  ContactListModelItem *clmi = itemFor( index );
275  GroupModelItem *gmi = dynamic_cast<GroupModelItem*>( clmi );
276  MetaContactModelItem *mcmi = dynamic_cast<MetaContactModelItem*>( clmi );
277 
278  if ( gmi && gmi->group() )
279  {
280  Kopete::Group* g = gmi->group();
281  switch ( role )
282  {
283  case Qt::DisplayRole:
284  if ( g == Kopete::Group::offline() )
285  return i18n( "%1 (%2)", g->displayName(), gmi->count() );
286  else
287  return i18n( "%1 (%2/%3)", g->displayName(), countConnected( gmi ), gmi->count() );
288  break;
289  case Qt::DecorationRole:
290  if ( g->isExpanded() )
291  {
292  if ( g->useCustomIcon() )
293  return g->icon();
294  else
295  return KIcon( KOPETE_GROUP_DEFAULT_OPEN_ICON );
296  }
297  else
298  {
299  if ( g->useCustomIcon() )
300  return g->icon();
301  else
302  return KIcon( KOPETE_GROUP_DEFAULT_CLOSED_ICON );
303  }
304  break;
305  case Kopete::Items::TypeRole:
306  return Kopete::Items::Group;
307  break;
308  case Kopete::Items::ObjectRole:
309  return qVariantFromValue( (QObject*)g );
310  break;
311  case Kopete::Items::UuidRole:
312  return QUuid().toString();
313  break;
314  case Kopete::Items::TotalCountRole:
315  return g->members().count();
316  break;
317  case Kopete::Items::ConnectedCountRole:
318  return countConnected( gmi );
319  break;
320  case Kopete::Items::OnlineStatusRole:
321  return OnlineStatus::Unknown;
322  break;
323  case Kopete::Items::IdRole:
324  return QString::number(g->groupId());
325  break;
326  case Kopete::Items::ExpandStateRole:
327  return g->isExpanded();
328  break;
329  }
330  }
331 
332  if ( mcmi && mcmi->metaContact() )
333  {
334  if ( role == Kopete::Items::MetaContactGroupRole )
335  return qVariantFromValue( (QObject*)mcmi->parent()->group() );
336  else if ( role == Kopete::Items::AlwaysVisible )
337  return mcmi->metaContact()->isAlwaysVisible();
338  else
339  return metaContactData( mcmi->metaContact(), role );
340  }
341 
342  return QVariant();
343 }
344 
345 Qt::ItemFlags ContactListTreeModel::flags( const QModelIndex &index ) const
346 {
347  if ( !index.isValid() )
348  return Qt::NoItemFlags;
349 
350  Qt::ItemFlags f(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
351 
352  // if it is a contact item, add the selectable flag
353  if ( index.data( Kopete::Items::TypeRole ) == Kopete::Items::MetaContact )
354  {
355  // TODO: for now we are only allowing drag-n-drop of a
356  // metacontact if all the accounts its contacts belong are online
357  ContactListModelItem *clmi = itemFor( index );
358  MetaContactModelItem *mcmi = dynamic_cast<MetaContactModelItem*>(clmi);
359  if (mcmi && mcmi->metaContact())
360  {
361  f |= Qt::ItemIsEditable;
362  bool online = true;
363  foreach(Kopete::Contact *c, mcmi->metaContact()->contacts())
364  {
365  if (!c->account()->isConnected())
366  {
367  online = false;
368  break;
369  }
370  }
371  if (online)
372  f = f | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
373  }
374  }
375  else if ( index.data( Kopete::Items::TypeRole ) == Kopete::Items::Group )
376  {
377  f |= Qt::ItemIsDropEnabled;
378  if ( m_manualGroupSorting )
379  f |= Qt::ItemIsDragEnabled;
380  }
381 
382  return f;
383 }
384 
385 bool ContactListTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
386  int row, int column, const QModelIndex &parent)
387 {
388  if (action == Qt::IgnoreAction)
389  return true;
390 
391  // for now only accepting drop of metacontacts
392  if (!data->hasFormat("application/kopete.metacontacts.list") && !data->hasFormat("application/kopete.group") &&
393  !data->hasUrls())
394  return false;
395 
396  // contactlist has only one column
397  if (column > 0)
398  return false;
399 
400  if ( data->hasUrls() )
401  {
402  return dropUrl( data, row, parent, action );
403  }
404  else if ( data->hasFormat("application/kopete.group") )
405  {
406  // we don't support dropping groups into another group or copying groups
407  if ( itemFor( parent ) != m_topLevelGroup || action != Qt::MoveAction )
408  return false;
409 
410  // decode the mime data
411  QByteArray encodedData = data->data("application/kopete.group");
412  QDataStream stream(&encodedData, QIODevice::ReadOnly);
413  QList<Kopete::Group*> groups;
414 
415  while (!stream.atEnd())
416  {
417  QString groupUuid;
418  stream >> groupUuid;
419  groups.append(Kopete::ContactList::self()->group( groupUuid.toUInt() ));
420  }
421 
422  GroupModelItem *newParent = dynamic_cast<GroupModelItem*>( itemFor( parent ) );
423  for ( int i=0; i < groups.count(); ++i )
424  {
425  GroupModelItem* gmi = m_groups.value( groups.at( i ) );
426  Q_ASSERT( gmi );
427 
428  int gIndex = gmi->index();
429  int gDesireIndex = row + i;
430 
431  // Check if mcDesireIndex isn't invalid
432  int mcCount = newParent->metaContactCount();
433  if ( gDesireIndex < mcCount )
434  gDesireIndex = mcCount;
435  else if ( gDesireIndex > newParent->count() )
436  gDesireIndex = newParent->count();
437 
438  // If the manual index is the same do nothing otherwise change possition
439  if ( gIndex == gDesireIndex )
440  continue;
441 
442  // We're moving group so temporary remove it so model is aware of the change.
443  beginRemoveRows( indexFor( gmi->parent() ), gIndex, gIndex );
444  gmi->remove();
445  endRemoveRows();
446 
447  // If gDesireIndex was after gIndex decrement it because we have removed group
448  if ( gIndex < gDesireIndex )
449  gDesireIndex--;
450 
451  beginInsertRows( parent, gDesireIndex, gDesireIndex );
452  newParent->insert( gDesireIndex, gmi );
453  endInsertRows();
454  }
455  }
456  else if ( data->hasFormat("application/kopete.metacontacts.list") )
457  {
458  // we don't support dropping things in an empty space
459  if ( !parent.isValid() )
460  return false;
461 
462  // decode the mime data
463  QByteArray encodedData = data->data("application/kopete.metacontacts.list");
464  QDataStream stream(&encodedData, QIODevice::ReadOnly);
465  QList<GroupMetaContactPair> items;
466 
467  while (!stream.atEnd())
468  {
469  QString line;
470  stream >> line;
471 
472  QStringList entry = line.split("/");
473 
474  QString grp = entry[0];
475  QString id = entry[1];
476 
477  GroupMetaContactPair pair;
478  pair.first = Kopete::ContactList::self()->group( grp.toUInt() );
479  pair.second = Kopete::ContactList::self()->metaContact( QUuid(id) );
480  items.append( pair );
481  }
482 
483  return dropMetaContacts( row, parent, action, items );
484  }
485 
486  return false;
487 }
488 
489 QModelIndex ContactListTreeModel::parent( const QModelIndex & index ) const
490 {
491  if ( !index.isValid() )
492  return QModelIndex();
493 
494  return indexFor( itemFor( index )->parent() );
495 }
496 
497 bool ContactListTreeModel::dropMetaContacts( int row, const QModelIndex &parent, Qt::DropAction action, const QList<GroupMetaContactPair> &items )
498 {
499  if ( items.isEmpty() )
500  return false;
501 
502  if ( ContactListModel::dropMetaContacts( row, parent, action, items ) )
503  return true;
504 
505  if ( parent.data( Kopete::Items::TypeRole ) == Kopete::Items::Group )
506  {
507  QObject* groupObject = qVariantValue<QObject*>( parent.data( Kopete::Items::ObjectRole ) );
508  Kopete::Group* group = qobject_cast<Kopete::Group*>(groupObject);
509 
510  // if we have metacontacts on the mime data, move them to this group
511  for ( int i = 0; i < items.count(); ++i )
512  {
513  GroupMetaContactPair pair = items.at( i );
514  if ( m_manualMetaContactSorting )
515  {
516  m_addContactPosition.insert( pair, row + i );
517  if ( pair.first == group )
518  addMetaContactToGroup( pair.second, group );
519  else if ( action == Qt::MoveAction )
520  pair.second->moveToGroup( pair.first, group );
521  else if ( action == Qt::CopyAction )
522  pair.second->addToGroup( group );
523  }
524  else if ( pair.first != group )
525  {
526  if ( action == Qt::MoveAction )
527  pair.second->moveToGroup( pair.first, group );
528  else if ( action == Qt::CopyAction )
529  pair.second->addToGroup( group );
530  }
531  }
532  return true;
533  }
534  return false;
535 }
536 
537 ContactListModelItem* ContactListTreeModel::itemFor( const QModelIndex& index ) const
538 {
539  Q_ASSERT( index.isValid() );
540  return static_cast<ContactListModelItem*>( index.internalPointer() );
541 }
542 
543 QModelIndex ContactListTreeModel::indexFor( ContactListModelItem* modelItem ) const
544 {
545  if ( modelItem == 0 )
546  return QModelIndex(); // Invisible Root Item
547 
548  if ( modelItem == m_topLevelGroup )
549  return createIndex( 0, 0, modelItem ); // TopLevel Group (is hidden in view with setRootIndex)
550  else
551  return createIndex( modelItem->index(), 0, modelItem );
552 }
553 
554 QModelIndexList ContactListTreeModel::indexListFor( Kopete::ContactListElement* cle ) const
555 {
556  QModelIndexList indexList;
557  Kopete::MetaContact *mc = dynamic_cast<Kopete::MetaContact*>(cle);
558 
559  // Contact list doesn't contain myself account contact so ignore it
560  if (mc && mc != Kopete::ContactList::self()->myself())
561  {
562  // metacontact handling
563  // search for all the groups in which this contact is
564  foreach( Kopete::Group *g, mc->groups() )
565  {
566  GroupMetaContactPair groupMetaContactPair( g, mc );
567  MetaContactModelItem* mcmi = m_metaContacts.value( groupMetaContactPair );
568  if ( mcmi )
569  {
570  QModelIndex mcIndex = indexFor( mcmi );
571  if ( mcIndex.isValid() )
572  indexList.append( mcIndex );
573  }
574  }
575  }
576  else if (!mc)
577  {
578  // group handling
579  Kopete::Group *g = dynamic_cast<Kopete::Group*>(cle);
580  if (g)
581  {
582  GroupModelItem* gmi = m_groups.value( g );
583  Q_ASSERT( gmi );
584  indexList.append( indexFor( gmi ) );
585  }
586  }
587 
588  return indexList;
589 }
590 
591 void ContactListTreeModel::handleContactDataChange(Kopete::MetaContact* mc)
592 {
593  // get all the indexes for this metacontact
594  QModelIndexList indexList = indexListFor(mc);
595 
596  // and now notify all the changes
597  foreach(QModelIndex index, indexList)
598  {
599  if ( !mc->isOnline() )
600  addMetaContactToGroup( mc, Kopete::Group::offline() );
601  else
602  removeMetaContactFromGroup( mc, Kopete::Group::offline() );
603 
604  // we need to emit the dataChanged signal to the groups this metacontact belongs to
605  // so that proxy filtering is aware of the changes, first we have to update the parent
606  // otherwise the group won't be expandable.
607  emit dataChanged(index.parent(), index.parent());
608  emit dataChanged(index, index);
609  }
610 }
611 
612 void ContactListTreeModel::appearanceConfigChanged()
613 {
614  AppearanceSettings* as = AppearanceSettings::self();
615  bool manualGroupSorting = (as->contactListGroupSorting() == AppearanceSettings::EnumContactListGroupSorting::Manual);
616  bool manualMetaContactSorting = (as->contactListMetaContactSorting() == AppearanceSettings::EnumContactListMetaContactSorting::Manual);
617 
618  if ( m_manualGroupSorting != manualGroupSorting || m_manualMetaContactSorting != manualMetaContactSorting )
619  {
620  saveModelSettings( "Tree" );
621  m_manualGroupSorting = manualGroupSorting;
622  m_manualMetaContactSorting = manualMetaContactSorting;
623  loadModelSettings( "Tree" );
624  }
625 }
626 
627 void ContactListTreeModel::loadContactList()
628 {
629  ContactListModel::loadContactList();
630 
631  addGroup( Kopete::Group::topLevel() );
632 
633  foreach ( Kopete::Group* g, Kopete::ContactList::self()->groups() )
634  addGroup( g );
635 
636  foreach ( Kopete::MetaContact* mc, Kopete::ContactList::self()->metaContacts() )
637  addMetaContact( mc );
638 
639  if ( m_manualGroupSorting || m_manualMetaContactSorting )
640  {
641  loadModelSettings( "Tree" );
642  reset();
643  }
644 }
645 
646 void ContactListTreeModel::saveModelSettingsImpl( QDomDocument& doc, QDomElement& rootElement )
647 {
648  if ( !m_manualGroupSorting && !m_manualMetaContactSorting )
649  return;
650 
651  if ( m_manualGroupSorting )
652  {
653  QDomElement groupRootElement = rootElement.firstChildElement( "GroupPositions" );
654  if ( !groupRootElement.isNull() )
655  rootElement.removeChild( groupRootElement );
656 
657  groupRootElement = doc.createElement( "GroupPositions" );
658  rootElement.appendChild( groupRootElement );
659 
660  int index = 0;
661  foreach ( ContactListModelItem* clmi, m_topLevelGroup->items() )
662  {
663  if ( clmi->isGroup() )
664  {
665  GroupModelItem* gmi = dynamic_cast<GroupModelItem*>( clmi );
666  if ( gmi->group() ) {
667  QDomElement groupElement = doc.createElement( "Group" );
668  groupElement.setAttribute( "uuid", gmi->group()->groupId() );
669  groupElement.setAttribute( "possition", index++ );
670  groupRootElement.appendChild( groupElement );
671  }
672  }
673  }
674  }
675 
676  if ( m_manualMetaContactSorting )
677  {
678  QDomElement metaContactRootElement = rootElement.firstChildElement("MetaContactPositions");
679  if ( !metaContactRootElement.isNull() )
680  rootElement.removeChild( metaContactRootElement );
681 
682  metaContactRootElement = doc.createElement( "MetaContactPositions" );
683  rootElement.appendChild( metaContactRootElement );
684 
685  QHashIterator<Kopete::Group*, GroupModelItem*> it( m_groups );
686  while ( it.hasNext() )
687  {
688  GroupModelItem* gmi = it.next().value();
689  QDomElement groupElement = doc.createElement( "Group" );
690  if ( ! gmi->group() ) continue;
691  groupElement.setAttribute( "uuid", gmi->group()->groupId() );
692  metaContactRootElement.appendChild( groupElement );
693 
694  int index = 0;
695  foreach ( ContactListModelItem* clmi, gmi->items() )
696  {
697  if ( !clmi->isGroup() )
698  {
699  MetaContactModelItem* mcmi = dynamic_cast<MetaContactModelItem*>( clmi );
700  if ( mcmi->metaContact() ) {
701  QDomElement metaContactElement = doc.createElement( "MetaContact" );
702  metaContactElement.setAttribute( "uuid", mcmi->metaContact()->metaContactId() );
703  metaContactElement.setAttribute( "possition", index++ );
704  groupElement.appendChild( metaContactElement );
705  }
706  }
707  }
708  }
709  }
710 }
711 
712 // Temporary hash, only used for sorting when contact list is loaded.
713 QHash<const ContactListModelItem*, int>* _contactListModelItemPosition = 0;
714 
715 bool contactListModelItemSort( const ContactListModelItem *item1, const ContactListModelItem *item2 )
716 {
717 
718  if ( item1->isGroup() != item2->isGroup() )
719  { //Groups are always after metaContacts
720  return !item1->isGroup();
721  }
722 
723  return _contactListModelItemPosition->value( item1, -1 ) < _contactListModelItemPosition->value( item2, -1 );
724 }
725 
726 void ContactListTreeModel::loadModelSettingsImpl( QDomElement& rootElement )
727 {
728  if ( rootElement.isNull() || (!m_manualGroupSorting && !m_manualMetaContactSorting) )
729  return;
730 
731  // Temporary hash for faster item lookup
732  QHash<uint, GroupModelItem*> uuidToGroup;
733  QHashIterator<Kopete::Group*, GroupModelItem*> it( m_groups );
734  while ( it.hasNext() )
735  {
736  GroupModelItem* gmi = it.next().value();
737  if ( ! gmi->group() ) continue;
738  uuidToGroup.insert( gmi->group()->groupId(), gmi );
739  }
740 
741  _contactListModelItemPosition = new QHash<const ContactListModelItem*, int>();
742  if ( m_manualGroupSorting )
743  {
744  QDomElement groupRootElement = rootElement.firstChildElement( "GroupPositions" );
745  if ( !groupRootElement.isNull() )
746  {
747  QDomNodeList groupList = groupRootElement.elementsByTagName("Group");
748 
749  for ( int index = 0; index < groupList.size(); ++index )
750  {
751  QDomElement groupElement = groupList.item( index ).toElement();
752  if ( groupElement.isNull() )
753  continue;
754 
755  // Put position into hash.
756  int uuid = groupElement.attribute( "uuid", "-1" ).toInt();
757  int groupPosition = groupElement.attribute( "possition", "-1" ).toInt();
758  GroupModelItem* gmi = uuidToGroup.value( uuid, 0 );
759  if ( gmi )
760  _contactListModelItemPosition->insert( gmi, groupPosition );
761  }
762  }
763  }
764 
765  if ( m_manualMetaContactSorting )
766  {
767  QDomElement metaContactRootElement = rootElement.firstChildElement("MetaContactPositions");
768  if ( !metaContactRootElement.isNull() )
769  {
770  QDomNodeList groupList = metaContactRootElement.elementsByTagName("Group");
771 
772  for ( int groupIndex = 0; groupIndex < groupList.size(); ++groupIndex )
773  {
774  QDomElement groupElement = groupList.item( groupIndex ).toElement();
775  if ( groupElement.isNull() )
776  continue;
777 
778  int gUuid = groupElement.attribute( "uuid", "-1" ).toInt();
779  GroupModelItem* gmi = uuidToGroup.value( gUuid, 0 );
780  if ( !gmi )
781  continue;
782 
783  // Temporary hash for faster item lookup
784  QHash<QUuid, MetaContactModelItem*> uuidToMetaContact;
785  foreach ( ContactListModelItem* clmi, gmi->items() )
786  {
787  if ( !clmi->isGroup() )
788  {
789  MetaContactModelItem* mcmi = dynamic_cast<MetaContactModelItem*>(clmi);
790  if ( mcmi->metaContact() )
791  uuidToMetaContact.insert( mcmi->metaContact()->metaContactId(), mcmi );
792  }
793  }
794 
795  QDomNodeList metaContactList = groupElement.elementsByTagName("MetaContact");
796  for ( int index = 0; index < metaContactList.size(); ++index )
797  {
798  QDomElement metaContactElement = metaContactList.item( index ).toElement();
799  if ( metaContactElement.isNull() )
800  continue;
801 
802  // Put position into hash.
803  QUuid uuid( metaContactElement.attribute( "uuid" ) );
804  int metaContactPosition = metaContactElement.attribute( "possition", "-1" ).toInt();
805  MetaContactModelItem* mcmi = uuidToMetaContact.value( uuid, 0 );
806  if ( mcmi )
807  _contactListModelItemPosition->insert( mcmi, metaContactPosition );
808  }
809  }
810  }
811  }
812 
813  m_topLevelGroup->sort( contactListModelItemSort );
814  delete _contactListModelItemPosition;
815  _contactListModelItemPosition = 0;
816 }
817 
818 
819 int ContactListModelItem::index() const
820 {
821  if ( mParent )
822  return mParent->indexOf( this );
823  else
824  return -1;
825 }
826 
827 bool ContactListModelItem::remove()
828 {
829  int i = index();
830  if ( i == -1 )
831  return false;
832 
833  mParent->removeAt( i );
834  mParent = 0;
835  return true;
836 }
837 
838 int GroupModelItem::metaContactCount() const
839 {
840  int mcCount = 0;
841  foreach ( ContactListModelItem* clmi, mItems )
842  {
843  if ( !clmi->isGroup() )
844  mcCount++;
845  }
846 
847  return mcCount;
848 }
849 
850 void GroupModelItem::sort( bool (*lessThan)(const ContactListModelItem*, const ContactListModelItem*) )
851 {
852  foreach ( ContactListModelItem* clmi, mItems )
853  clmi->sort( lessThan );
854 
855  qStableSort( mItems.begin(), mItems.end(), lessThan );
856 }
857 
858 int GroupModelItem::indexOf( const ContactListModelItem* item ) const
859 {
860  // FIXME: why I cannot use "return mItems.indexOf( item )" I get compilation error???
861  for ( int i = 0; i < mItems.count(); ++i )
862  {
863  if ( mItems.at( i ) == item )
864  return i;
865  }
866 
867  return -1;
868 }
869 
870 }
871 
872 }
873 
874 #include "contactlisttreemodel.moc"
875 //kate: tab-width 4
Kopete::UI::ContactListTreeModel::~ContactListTreeModel
~ContactListTreeModel()
Definition: contactlisttreemodel.cpp:49
QModelIndex
QDomElement::elementsByTagName
QDomNodeList elementsByTagName(const QString &tagname) const
Kopete::UI::ContactListTreeModel::loadContactList
virtual void loadContactList()
Definition: contactlisttreemodel.cpp:627
Kopete::UI::ContactListModelItem::remove
bool remove()
Definition: contactlisttreemodel.cpp:827
Kopete::UI::ContactListTreeModel::dropMimeData
virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
Definition: contactlisttreemodel.cpp:385
QHash::insert
iterator insert(const Key &key, const T &value)
QDomNodeList::item
QDomNode item(int index) const
QMimeData::data
QByteArray data(const QString &mimeType) const
Kopete::UI::MetaContactModelItem
Definition: contactlisttreemodel_p.h:79
Kopete::UI::ContactListTreeModel::removeGroup
virtual void removeGroup(Kopete::Group *)
Definition: contactlisttreemodel.cpp:99
Kopete::UI::ContactListTreeModel::addMetaContactToGroup
virtual void addMetaContactToGroup(Kopete::MetaContact *, Kopete::Group *)
Definition: contactlisttreemodel.cpp:114
Kopete::UI::ContactListModelItem::sort
virtual void sort(bool(*lessThan)(const ContactListModelItem *, const ContactListModelItem *))
Definition: contactlisttreemodel_p.h:69
Kopete::UI::ContactListTreeModel::flags
virtual Qt::ItemFlags flags(const QModelIndex &index) const
Definition: contactlisttreemodel.cpp:345
KOPETE_GROUP_DEFAULT_CLOSED_ICON
#define KOPETE_GROUP_DEFAULT_CLOSED_ICON
Definition: kopeteitembase.h:27
QDomNode::appendChild
QDomNode appendChild(const QDomNode &newChild)
Kopete::UI::ContactListModel::GroupMetaContactPair
QPair< Kopete::Group *, Kopete::MetaContact * > GroupMetaContactPair
Definition: contactlistmodel.h:82
kopeteitembase.h
Contains definitions common between model items.
Kopete::UI::ContactListModelItem::isGroup
virtual bool isGroup() const
Definition: contactlisttreemodel_p.h:40
QByteArray
Kopete::UI::ContactListTreeModel::ContactListTreeModel
ContactListTreeModel(QObject *parent=0)
Definition: contactlisttreemodel.cpp:42
QDomElement::attribute
QString attribute(const QString &name, const QString &defValue) const
Kopete::UI::ContactListModel::metaContactData
QVariant metaContactData(const Kopete::MetaContact *mc, int role) const
Definition: contactlistmodel.cpp:505
QMimeData::hasFormat
virtual bool hasFormat(const QString &mimeType) const
QDataStream
Kopete::UI::MetaContactModelItem::metaContact
Kopete::MetaContact * metaContact() const
Definition: contactlisttreemodel_p.h:86
QHashIterator::hasNext
bool hasNext() const
QDomNodeList
Kopete::UI::ContactListTreeModel::appearanceConfigChanged
virtual void appearanceConfigChanged()
Definition: contactlisttreemodel.cpp:612
QList::at
const T & at(int i) const
Kopete::Items::TotalCountRole
const int TotalCountRole
Definition: kopeteitembase.h:39
Kopete::UI::_contactListModelItemPosition
QHash< const ContactListModelItem *, int > * _contactListModelItemPosition
Definition: contactlisttreemodel.cpp:713
KOPETE_GROUP_DEFAULT_OPEN_ICON
#define KOPETE_GROUP_DEFAULT_OPEN_ICON
Definition: kopeteitembase.h:26
Kopete::UI::GroupModelItem::at
ContactListModelItem * at(int i) const
Definition: contactlisttreemodel_p.h:141
QUuid
Kopete::UI::ContactListModelItem::count
virtual int count() const
Definition: contactlisttreemodel_p.h:45
Kopete::Items::OnlineStatusRole
const int OnlineStatusRole
Definition: kopeteitembase.h:36
Kopete::UI::GroupModelItem::insert
void insert(int i, ContactListModelItem *item)
Definition: contactlisttreemodel_p.h:135
Kopete::Items::MetaContactGroupRole
const int MetaContactGroupRole
Definition: kopeteitembase.h:53
Kopete::Items::UuidRole
const int UuidRole
Definition: kopeteitembase.h:38
Kopete::UI::ContactListModelItem::index
int index() const
Definition: contactlisttreemodel.cpp:819
Kopete::UI::ContactListModelItem
Definition: contactlisttreemodel_p.h:34
QMimeData
Kopete::UI::ContactListModel::dropUrl
bool dropUrl(const QMimeData *data, int row, const QModelIndex &parent, Qt::DropAction action)
Definition: contactlistmodel.cpp:394
Kopete::UI::ContactListTreeModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
Definition: contactlisttreemodel.cpp:213
QDomNode::toElement
QDomElement toElement() const
Kopete::Items::MetaContact
Definition: kopeteitembase.h:57
QAbstractItemModel::reset
void reset()
QModelIndex::isValid
bool isValid() const
QString::number
QString number(int n, int base)
Kopete::UI::ContactListModel::addMetaContact
virtual void addMetaContact(Kopete::MetaContact *)
Definition: contactlistmodel.cpp:268
QList::count
int count(const T &value) const
QList::append
void append(const T &value)
Kopete::Items::Group
Definition: kopeteitembase.h:57
Kopete::UI::ContactListTreeModel::removeMetaContactFromGroup
virtual void removeMetaContactFromGroup(Kopete::MetaContact *, Kopete::Group *)
Definition: contactlisttreemodel.cpp:175
QAbstractItemModel::dataChanged
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
QHash
QAbstractItemModel::endInsertRows
void endInsertRows()
QObject
QDomElement::setAttribute
void setAttribute(const QString &name, const QString &value)
Kopete::UI::ContactListModel::m_manualGroupSorting
bool m_manualGroupSorting
Definition: contactlistmodel.h:92
QString::toInt
int toInt(bool *ok, int base) const
QList::isEmpty
bool isEmpty() const
QHashIterator
QAbstractItemModel::beginRemoveRows
void beginRemoveRows(const QModelIndex &parent, int first, int last)
Kopete::UI::ContactListModel
Definition: contactlistmodel.h:42
Kopete::UI::ContactListModelItem::parent
GroupModelItem * parent() const
Definition: contactlisttreemodel_p.h:60
Kopete::UI::ContactListTreeModel::dropMetaContacts
virtual bool dropMetaContacts(int row, const QModelIndex &parent, Qt::DropAction action, const QList< GroupMetaContactPair > &items)
Definition: contactlisttreemodel.cpp:497
Kopete::UI::GroupModelItem::sort
virtual void sort(bool(*lessThan)(const ContactListModelItem *, const ContactListModelItem *))
Definition: contactlisttreemodel.cpp:850
Kopete::Items::TypeRole
const int TypeRole
Qt Model Role Definitions.
Definition: kopeteitembase.h:34
QModelIndex::internalPointer
void * internalPointer() const
Kopete::UI::GroupModelItem::append
void append(ContactListModelItem *item)
Definition: contactlisttreemodel_p.h:129
Kopete::UI::GroupModelItem::items
QList< ContactListModelItem * > items() const
Definition: contactlisttreemodel_p.h:146
QString
QList
Kopete::UI::GroupModelItem::group
Kopete::Group * group() const
Definition: contactlisttreemodel_p.h:124
QHash::remove
int remove(const Key &key)
Kopete::Items::IdRole
const int IdRole
Definition: kopeteitembase.h:41
Kopete::UI::ContactListTreeModel::addGroup
virtual void addGroup(Kopete::Group *)
Definition: contactlisttreemodel.cpp:78
Kopete::UI::ContactListModel::setData
virtual bool setData(const QModelIndex &index, const QVariant &value, const int role)
Definition: contactlistmodel.cpp:153
QModelIndex::parent
QModelIndex parent() const
Kopete::UI::GroupModelItem::count
virtual int count() const
Definition: contactlisttreemodel_p.h:112
QDataStream::atEnd
bool atEnd() const
Kopete::UI::ContactListTreeModel::loadModelSettingsImpl
virtual void loadModelSettingsImpl(QDomElement &rootElement)
Definition: contactlisttreemodel.cpp:726
QStringList
QPair
Kopete::UI::ContactListTreeModel::hasChildren
virtual bool hasChildren(const QModelIndex &parent=QModelIndex()) const
Definition: contactlisttreemodel.cpp:205
Kopete::UI::ContactListModel::loadContactList
virtual void loadContactList()
Definition: contactlistmodel.cpp:322
QAbstractItemModel::createIndex
QModelIndex createIndex(int row, int column, void *ptr) const
Kopete::Items::AlwaysVisible
const int AlwaysVisible
Definition: kopeteitembase.h:54
contactlisttreemodel.h
QHash::value
const T value(const Key &key) const
QDomNode::removeChild
QDomNode removeChild(const QDomNode &oldChild)
QHashIterator::next
Item next()
QDomDocument
QAbstractItemModel::beginInsertRows
void beginInsertRows(const QModelIndex &parent, int first, int last)
Kopete::UI::ContactListTreeModel::removeMetaContact
virtual void removeMetaContact(Kopete::MetaContact *)
Definition: contactlisttreemodel.cpp:70
QDomNode::isNull
bool isNull() const
Kopete::UI::ContactListTreeModel::saveModelSettingsImpl
virtual void saveModelSettingsImpl(QDomDocument &doc, QDomElement &rootElement)
Definition: contactlisttreemodel.cpp:646
Kopete::Items::ConnectedCountRole
const int ConnectedCountRole
Definition: kopeteitembase.h:40
Kopete::UI::ContactListModel::dropMetaContacts
virtual bool dropMetaContacts(int row, const QModelIndex &parent, Qt::DropAction action, const QList< GroupMetaContactPair > &items)
Definition: contactlistmodel.cpp:462
Kopete::UI::ContactListTreeModel::data
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
Definition: contactlisttreemodel.cpp:266
QMimeData::hasUrls
bool hasUrls() const
QModelIndex::data
QVariant data(int role) const
Kopete::Items::ExpandStateRole
const int ExpandStateRole
Definition: kopeteitembase.h:51
QDomNode::firstChildElement
QDomElement firstChildElement(const QString &tagName) const
QStringList::split
QStringList split(const QString &sep, const QString &str, bool allowEmptyEntries)
QVariant::toBool
bool toBool() const
Kopete::UI::ContactListModel::saveModelSettings
bool saveModelSettings(const QString &modelType)
Definition: contactlistmodel.cpp:213
Kopete::UI::ContactListTreeModel::addMetaContact
virtual void addMetaContact(Kopete::MetaContact *)
Definition: contactlisttreemodel.cpp:54
Kopete::UI::GroupModelItem::metaContactCount
virtual int metaContactCount() const
Definition: contactlisttreemodel.cpp:838
QHash::contains
bool contains(const Key &key) const
Kopete::UI::ContactListModel::removeMetaContact
virtual void removeMetaContact(Kopete::MetaContact *)
Definition: contactlistmodel.cpp:280
Kopete::UI::ContactListModel::handleContactDataChange
void handleContactDataChange()
Definition: contactlistmodel.cpp:348
QDomNodeList::size
int size() const
QDomDocument::createElement
QDomElement createElement(const QString &tagName)
QAbstractItemModel::endRemoveRows
void endRemoveRows()
Kopete::UI::ContactListModel::loadModelSettings
bool loadModelSettings(const QString &modelType)
Definition: contactlistmodel.cpp:169
Kopete::Items::ObjectRole
const int ObjectRole
Definition: kopeteitembase.h:50
Kopete::UI::GroupModelItem::indexOf
int indexOf(const ContactListModelItem *item) const
Definition: contactlisttreemodel.cpp:858
Kopete::UI::ContactListTreeModel::setData
virtual bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole)
Definition: contactlisttreemodel.cpp:240
QObject::parent
QObject * parent() const
QDomElement
Kopete::UI::GroupModelItem
Definition: contactlisttreemodel_p.h:95
Kopete::UI::contactListModelItemSort
bool contactListModelItemSort(const ContactListModelItem *item1, const ContactListModelItem *item2)
Definition: contactlisttreemodel.cpp:715
Kopete::UI::ContactListTreeModel::rowCount
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
Definition: contactlisttreemodel.cpp:197
QUuid::toString
QString toString() const
Kopete::UI::ContactListModelItem::hasChildren
virtual bool hasChildren() const
Definition: contactlisttreemodel_p.h:55
contactlisttreemodel_p.h
QString::toUInt
uint toUInt(bool *ok, int base) const
QVariant
Qt::ItemFlags
typedef ItemFlags
Kopete::UI::ContactListModel::m_manualMetaContactSorting
bool m_manualMetaContactSorting
Definition: contactlistmodel.h:93
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:29:08 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kopete/kopete

Skip menu "kopete/kopete"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdenetwork API Reference

Skip menu "kdenetwork API Reference"
  • kget
  • kopete
  •   kopete
  •   libkopete
  • krdc
  • krfb

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal