• 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.12
  • kdenetwork
  • kopete
  • kopete
  • contactlist
contactlistplainmodel.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 "contactlistplainmodel.h"
22 
23 #include <QMimeData>
24 #include <QDomDocument>
25 
26 #include "kopeteaccount.h"
27 #include "kopetemetacontact.h"
28 #include "kopetecontact.h"
29 #include "kopetecontactlist.h"
30 #include "kopeteitembase.h"
31 #include "kopeteappearancesettings.h"
32 
33 namespace Kopete {
34 
35 namespace UI {
36 
37 ContactListPlainModel::ContactListPlainModel( QObject* parent )
38  : ContactListModel( parent )
39 {
40 }
41 
42 ContactListPlainModel::~ContactListPlainModel()
43 {
44  saveModelSettings( "Plain" );
45 }
46 
47 void ContactListPlainModel::addMetaContact( Kopete::MetaContact *mc )
48 {
49  ContactListModel::addMetaContact( mc );
50  addMetaContactImpl( mc );
51 }
52 
53 void ContactListPlainModel::addMetaContactImpl( Kopete::MetaContact *mc )
54 {
55  int mcIndex = m_contacts.indexOf( mc );
56  int mcDesireIndex = m_contacts.count();
57 
58  // If we use manual sorting we most likely will have possition where the metaContact should be inserted.
59  if ( m_manualMetaContactSorting )
60  {
61  if ( m_addContactPosition.contains( mc ) )
62  {
63  mcDesireIndex = m_addContactPosition.value( mc );
64  m_addContactPosition.remove( mc );
65  }
66  }
67 
68  // Check if mcDesireIndex isn't invalid (shouldn't happen)
69  if ( mcDesireIndex < 0 || mcDesireIndex > m_contacts.count() )
70  mcDesireIndex = m_contacts.count();
71 
72  if ( mcIndex != -1 )
73  {
74  // If the manual index is the same do nothing otherwise change possition
75  if ( mcIndex == mcDesireIndex )
76  return;
77 
78  // We're moving metaContact so temporary remove it so model is aware of the change.
79  beginRemoveRows( QModelIndex(), mcIndex, mcIndex );
80  m_contacts.removeAt( mcIndex );
81  endRemoveRows();
82 
83  // If mcDesireIndex was after mcIndex decrement it because we have removed metaContact
84  if ( mcIndex < mcDesireIndex )
85  mcDesireIndex--;
86  }
87 
88  beginInsertRows( QModelIndex(), mcDesireIndex, mcDesireIndex );
89  m_contacts.insert( mcDesireIndex, mc );
90  endInsertRows();
91 }
92 
93 void ContactListPlainModel::removeMetaContact( Kopete::MetaContact *mc )
94 {
95  ContactListModel::removeMetaContact( mc );
96 
97  // if the mc is not on the list anymore, just returns
98  int offset = m_contacts.indexOf( mc );
99  if (offset == -1)
100  return;
101 
102  beginRemoveRows(QModelIndex(), offset, offset);
103  m_contacts.removeAt(offset);
104  endRemoveRows();
105 }
106 
107 int ContactListPlainModel::rowCount( const QModelIndex& parent ) const
108 {
109  if ( !parent.isValid() )
110  return m_contacts.count();
111  else
112  return 0;
113 }
114 
115 bool ContactListPlainModel::hasChildren( const QModelIndex& parent ) const
116 {
117  if ( !parent.isValid() )
118  return !m_contacts.isEmpty();
119  else
120  return false;
121 }
122 
123 QModelIndex ContactListPlainModel::index( int row, int column, const QModelIndex & parent ) const
124 {
125  if ( row < 0 || row >= rowCount( parent ) )
126  return QModelIndex();
127 
128  QModelIndex idx;
129  if ( !parent.isValid() )
130  return createIndex( row, column, m_contacts[row] );
131  else
132  return QModelIndex();
133 }
134 
135 
136 QVariant ContactListPlainModel::data ( const QModelIndex & index, int role ) const
137 {
138  if ( !index.isValid() )
139  return QVariant();
140 
141  using namespace Kopete;
142 
143  /* do all the casting up front. I need to profile to see how expensive this is though */
144  Kopete::ContactListElement *cle = static_cast<Kopete::ContactListElement*>( index.internalPointer() );
145  Kopete::MetaContact *mc = dynamic_cast<Kopete::MetaContact*>(cle);
146 
147  return metaContactData( mc, role );
148 }
149 
150 Qt::ItemFlags ContactListPlainModel::flags( const QModelIndex &index ) const
151 {
152  if ( !index.isValid() )
153  return (m_manualMetaContactSorting) ? Qt::ItemIsDropEnabled : Qt::NoItemFlags;
154 
155  Qt::ItemFlags f(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
156 
157  // if it is a contact item, add the selectable flag
158  if ( index.data( Kopete::Items::TypeRole ) == Kopete::Items::MetaContact )
159  {
160  // TODO: for now we are only allowing drag-n-drop of a
161  // metacontact if all the accounts its contacts belong are online
162  Kopete::ContactListElement *cle = static_cast<Kopete::ContactListElement*>( index.internalPointer() );
163  Kopete::MetaContact *mc = dynamic_cast<Kopete::MetaContact*>(cle);
164  if (mc)
165  {
166  f |= Qt::ItemIsEditable;
167  bool online = true;
168  foreach(Kopete::Contact *c, mc->contacts())
169  {
170  if (!c->account()->isConnected())
171  {
172  online = false;
173  break;
174  }
175  }
176  if (online)
177  f = f | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
178  }
179  }
180 
181  return f;
182 }
183 
184 bool ContactListPlainModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
185  int row, int column, const QModelIndex &parent)
186 {
187  if ( action == Qt::IgnoreAction )
188  return true;
189 
190  // for now only accepting drop of metacontacts
191  // TODO: support dropping of files in metacontacts to allow file transfers
192  if ( !data->hasFormat("application/kopete.metacontacts.list") && !data->hasUrls() )
193  return false;
194 
195  // contactlist has only one column
196  if (column > 0)
197  return false;
198 
199  if ( data->hasUrls() )
200  {
201  return dropUrl( data, row, parent, action );
202  }
203  else if ( data->hasFormat("application/kopete.metacontacts.list") )
204  {
205  // decode the mime data
206  QByteArray encodedData = data->data("application/kopete.metacontacts.list");
207  QDataStream stream(&encodedData, QIODevice::ReadOnly);
208  QList<GroupMetaContactPair> items;
209 
210  while (!stream.atEnd())
211  {
212  QString line;
213  stream >> line;
214 
215  QStringList entry = line.split("/");
216 
217  QString grp = entry[0];
218  QString id = entry[1];
219 
220  GroupMetaContactPair pair;
221  pair.first = Kopete::ContactList::self()->group( grp.toUInt() );
222  pair.second = Kopete::ContactList::self()->metaContact( QUuid(id) );
223  items.append( pair );
224  }
225 
226  return dropMetaContacts( row, parent, action, items );
227  }
228 
229  return false;
230 }
231 
232 bool ContactListPlainModel::dropMetaContacts( int row, const QModelIndex &parent, Qt::DropAction action, const QList<GroupMetaContactPair> &items )
233 {
234  if ( items.isEmpty() )
235  return false;
236 
237  if ( ContactListModel::dropMetaContacts( row, parent, action, items ) )
238  return true;
239 
240  if ( !parent.isValid() )
241  {
242  for ( int i = 0; i < items.count(); ++i )
243  {
244  if ( m_manualMetaContactSorting )
245  {
246  GroupMetaContactPair pair = items.at( i );
247  m_addContactPosition.insert( pair.second, row + i );
248  addMetaContactImpl( pair.second );
249  }
250  }
251  return true;
252  }
253 
254  return false;
255 }
256 
257 QModelIndex ContactListPlainModel::parent( const QModelIndex& ) const
258 {
259  return QModelIndex();
260 }
261 
262 QModelIndexList ContactListPlainModel::indexListFor( Kopete::ContactListElement* cle ) const
263 {
264  QModelIndexList indexList;
265  Kopete::MetaContact *mc = dynamic_cast<Kopete::MetaContact*>(cle);
266 
267  // Contact list doesn't contain myself account contact so ignore it
268  if (mc && mc != Kopete::ContactList::self()->myself())
269  {
270  int mcPos = m_contacts.indexOf( mc );
271  if ( mcPos != -1 )
272  {
273  QModelIndex mcIndex = index(mcPos, 0);
274  if (mcIndex.isValid())
275  indexList.append(mcIndex);
276  }
277  }
278 
279  return indexList;
280 }
281 
282 void ContactListPlainModel::handleContactDataChange(Kopete::MetaContact* mc)
283 {
284  // get all the indexes for this metacontact
285  QModelIndexList indexList = indexListFor(mc);
286 
287  // and now notify all the changes
288  foreach(QModelIndex index, indexList)
289  emit dataChanged(index, index);
290 }
291 
292 void ContactListPlainModel::appearanceConfigChanged()
293 {
294  AppearanceSettings* as = AppearanceSettings::self();
295  bool manualGroupSorting = (as->contactListGroupSorting() == AppearanceSettings::EnumContactListGroupSorting::Manual);
296  bool manualMetaContactSorting = (as->contactListMetaContactSorting() == AppearanceSettings::EnumContactListMetaContactSorting::Manual);
297 
298  if ( m_manualMetaContactSorting != manualMetaContactSorting )
299  {
300  saveModelSettings( "Plain" );
301  m_manualGroupSorting = manualGroupSorting;
302  m_manualMetaContactSorting = manualMetaContactSorting;
303  loadModelSettings( "Plain" );
304  }
305 }
306 
307 void ContactListPlainModel::loadContactList()
308 {
309  ContactListModel::loadContactList();
310 
311  foreach ( Kopete::MetaContact* mc, Kopete::ContactList::self()->metaContacts() )
312  addMetaContact( mc );
313 
314  if ( m_manualMetaContactSorting )
315  {
316  loadModelSettings( "Plain" );
317  reset();
318  }
319 }
320 
321 void ContactListPlainModel::saveModelSettingsImpl( QDomDocument& doc, QDomElement& rootElement )
322 {
323  if ( m_manualMetaContactSorting )
324  {
325  QDomElement metaContactRootElement = rootElement.firstChildElement( "MetaContactPositions" );
326  if ( !metaContactRootElement.isNull() )
327  rootElement.removeChild( metaContactRootElement );
328 
329  metaContactRootElement = doc.createElement( "MetaContactPositions" );
330  rootElement.appendChild( metaContactRootElement );
331 
332  for ( int i = 0; i < m_contacts.count(); ++i )
333  {
334  Kopete::MetaContact* mc = m_contacts.value( i );
335  QDomElement metaContactElement = doc.createElement( "MetaContact" );
336  metaContactElement.setAttribute( "uuid", mc->metaContactId() );
337  metaContactElement.setAttribute( "possition", i );
338  metaContactRootElement.appendChild( metaContactElement );
339  }
340  }
341 }
342 
343 // Temporary hash, only used for sorting when contact list is loaded.
344 QHash<const Kopete::MetaContact*, int>* _metaContactPositionPlain = 0;
345 
346 bool manualMetaContactSort( const Kopete::MetaContact *mc1, const Kopete::MetaContact *mc2 )
347 {
348  return _metaContactPositionPlain->value( mc1, -1 ) < _metaContactPositionPlain->value( mc2, -1 );
349 }
350 
351 void ContactListPlainModel::loadModelSettingsImpl( QDomElement& rootElement )
352 {
353  if ( !m_manualMetaContactSorting )
354  return;
355 
356  if ( m_manualMetaContactSorting )
357  {
358  QDomElement metaContactRootElement = rootElement.firstChildElement( "MetaContactPositions" );
359  if ( !metaContactRootElement.isNull() )
360  {
361  // Temporary hash for faster item lookup
362  QHash<QUuid, const Kopete::MetaContact*> uuidToMetaContact;
363  foreach( const Kopete::MetaContact* mc, m_contacts )
364  uuidToMetaContact.insert( mc->metaContactId(), mc );
365 
366  _metaContactPositionPlain = new QHash<const Kopete::MetaContact*, int>();
367  QDomNodeList metaContactList = metaContactRootElement.elementsByTagName( "MetaContact" );
368 
369  for ( int index = 0; index < metaContactList.size(); ++index )
370  {
371  QDomElement metaContactElement = metaContactList.item( index ).toElement();
372  if ( metaContactElement.isNull() )
373  continue;
374 
375  // Put position into hash.
376  QUuid uuid( metaContactElement.attribute( "uuid" ) );
377  int metaContactPosition = metaContactElement.attribute( "possition", "-1" ).toInt();
378  const Kopete::MetaContact* mc = uuidToMetaContact.value( uuid, 0 );
379  if ( mc )
380  _metaContactPositionPlain->insert( mc, metaContactPosition );
381  }
382 
383  qStableSort( m_contacts.begin(), m_contacts.end(), manualMetaContactSort );
384 
385  delete _metaContactPositionPlain;
386  _metaContactPositionPlain = 0;
387  }
388  }
389 }
390 
391 }
392 
393 }
394 
395 #include "contactlistplainmodel.moc"
396 //kate: tab-width 4
Kopete::UI::ContactListModel::GroupMetaContactPair
QPair< Kopete::Group *, Kopete::MetaContact * > GroupMetaContactPair
Definition: contactlistmodel.h:82
kopeteitembase.h
Contains definitions common between model items.
Kopete::UI::ContactListPlainModel::~ContactListPlainModel
~ContactListPlainModel()
Definition: contactlistplainmodel.cpp:42
Kopete::UI::ContactListModel::metaContactData
QVariant metaContactData(const Kopete::MetaContact *mc, int role) const
Definition: contactlistmodel.cpp:505
Kopete::UI::ContactListPlainModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
Definition: contactlistplainmodel.cpp:123
Kopete::UI::ContactListPlainModel::data
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
Definition: contactlistplainmodel.cpp:136
Kopete::UI::ContactListPlainModel::rowCount
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
Definition: contactlistplainmodel.cpp:107
QObject
Kopete::UI::ContactListPlainModel::removeMetaContact
virtual void removeMetaContact(Kopete::MetaContact *)
Definition: contactlistplainmodel.cpp:93
Kopete::UI::ContactListModel::dropUrl
bool dropUrl(const QMimeData *data, int row, const QModelIndex &parent, Qt::DropAction action)
Definition: contactlistmodel.cpp:394
Kopete::Items::MetaContact
Definition: kopeteitembase.h:57
Kopete::UI::ContactListModel::addMetaContact
virtual void addMetaContact(Kopete::MetaContact *)
Definition: contactlistmodel.cpp:268
Kopete::UI::ContactListPlainModel::ContactListPlainModel
ContactListPlainModel(QObject *parent=0)
Definition: contactlistplainmodel.cpp:37
Kopete::UI::ContactListModel::m_manualGroupSorting
bool m_manualGroupSorting
Definition: contactlistmodel.h:92
Kopete::UI::ContactListPlainModel::flags
virtual Qt::ItemFlags flags(const QModelIndex &index) const
Definition: contactlistplainmodel.cpp:150
Kopete::UI::_metaContactPositionPlain
QHash< const Kopete::MetaContact *, int > * _metaContactPositionPlain
Definition: contactlistplainmodel.cpp:344
Kopete::UI::ContactListModel
Definition: contactlistmodel.h:42
Kopete::UI::ContactListPlainModel::loadModelSettingsImpl
virtual void loadModelSettingsImpl(QDomElement &rootElement)
Definition: contactlistplainmodel.cpp:351
Kopete::UI::ContactListPlainModel::hasChildren
virtual bool hasChildren(const QModelIndex &parent=QModelIndex()) const
Definition: contactlistplainmodel.cpp:115
Kopete::UI::manualMetaContactSort
bool manualMetaContactSort(const Kopete::MetaContact *mc1, const Kopete::MetaContact *mc2)
Definition: contactlistplainmodel.cpp:346
Kopete::Items::TypeRole
const int TypeRole
Qt Model Role Definitions.
Definition: kopeteitembase.h:34
contactlistplainmodel.h
Kopete::UI::ContactListPlainModel::appearanceConfigChanged
virtual void appearanceConfigChanged()
Definition: contactlistplainmodel.cpp:292
Kopete::UI::ContactListModel::loadContactList
virtual void loadContactList()
Definition: contactlistmodel.cpp:322
Kopete::UI::ContactListPlainModel::saveModelSettingsImpl
virtual void saveModelSettingsImpl(QDomDocument &doc, QDomElement &rootElement)
Definition: contactlistplainmodel.cpp:321
Kopete::UI::ContactListPlainModel::loadContactList
virtual void loadContactList()
Definition: contactlistplainmodel.cpp:307
Kopete::UI::ContactListPlainModel::addMetaContact
virtual void addMetaContact(Kopete::MetaContact *)
Definition: contactlistplainmodel.cpp:47
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::ContactListPlainModel::dropMimeData
virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
Definition: contactlistplainmodel.cpp:184
Kopete::UI::ContactListModel::saveModelSettings
bool saveModelSettings(const QString &modelType)
Definition: contactlistmodel.cpp:213
Kopete::UI::ContactListModel::removeMetaContact
virtual void removeMetaContact(Kopete::MetaContact *)
Definition: contactlistmodel.cpp:280
Kopete::UI::ContactListPlainModel::parent
virtual QModelIndex parent(const QModelIndex &index) const
Definition: contactlistplainmodel.cpp:257
Kopete::UI::ContactListModel::handleContactDataChange
void handleContactDataChange()
Definition: contactlistmodel.cpp:348
Kopete::UI::ContactListModel::loadModelSettings
bool loadModelSettings(const QString &modelType)
Definition: contactlistmodel.cpp:169
Kopete::UI::ContactListPlainModel::dropMetaContacts
virtual bool dropMetaContacts(int row, const QModelIndex &parent, Qt::DropAction action, const QList< GroupMetaContactPair > &items)
Definition: contactlistplainmodel.cpp:232
Kopete::UI::ContactListModel::m_manualMetaContactSorting
bool m_manualMetaContactSorting
Definition: contactlistmodel.h:93
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:53:40 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