• 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
contactlistproxymodel.cpp
Go to the documentation of this file.
1 /*
2  Kopete Contactlist Model
3 
4  Copyright (c) 2007 by Matt Rogers <mattr@kde.org>
5 
6  Kopete (c) 2002-2007 by the Kopete developers <kopete-devel@kde.org>
7 
8  *************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  *************************************************************************
16 */
17 
18 #include "contactlistproxymodel.h"
19 
20 #include <QStandardItem>
21 #include <QList>
22 #include <QTimer>
23 
24 #include "kopetegroup.h"
25 #include "kopetemetacontact.h"
26 #include "kopetecontactlist.h"
27 #include "kopetecontact.h"
28 #include "kopeteappearancesettings.h"
29 #include "kopeteitembase.h"
30 #include <kabc/stdaddressbook.h>
31 
32 namespace Kopete {
33 
34 namespace UI {
35 
36 ContactListProxyModel::ContactListProxyModel(QObject* parent)
37  : QSortFilterProxyModel(parent), rootRowCount(0), sortScheduled(false)
38 {
39  setDynamicSortFilter(true);
40  sort( 0, Qt::AscendingOrder );
41  connect ( Kopete::AppearanceSettings::self(), SIGNAL(configChanged()), this, SLOT(slotConfigChanged()) );
42 
43  // Workaround Qt sorting bug
44  connect( this, SIGNAL(rowsInserted(QModelIndex,int,int)),
45  this, SLOT(proxyRowsInserted(QModelIndex,int,int)) );
46  connect( this, SIGNAL(rowsRemoved(QModelIndex,int,int)),
47  this, SLOT(proxyRowsRemoved(QModelIndex,int,int)) );
48  connect( this, SIGNAL(modelReset()),
49  this, SLOT(proxyCheckSort()) );
50  connect( this, SIGNAL(layoutChanged()),
51  this, SLOT(proxyCheckSort()) );
52 
53 }
54 
55 ContactListProxyModel::~ContactListProxyModel()
56 {
57 
58 }
59 
60 void ContactListProxyModel::slotConfigChanged()
61 {
62  kDebug(14001) << "config changed";
63  invalidate();
64 }
65 
66 bool ContactListProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
67 {
68  int leftType = left.data( Kopete::Items::TypeRole ).toInt();
69  if ( leftType != right.data( Kopete::Items::TypeRole ).toInt() )
70  return (leftType == Kopete::Items::MetaContact); // MetaContacts are always on top.
71 
72  if ( leftType == Kopete::Items::Group )
73  {
74  switch ( Kopete::AppearanceSettings::self()->contactListGroupSorting() )
75  {
76  case Kopete::AppearanceSettings::EnumContactListGroupSorting::Manual:
77  return left.row() < right.row();
78  case Kopete::AppearanceSettings::EnumContactListGroupSorting::Name:
79  default:
80  QString leftName = left.data( Qt::DisplayRole ).toString();
81  QString rightName = right.data( Qt::DisplayRole ).toString();
82 
83  // Force the offline group to the bottom
84  QObject* groupObjectLeft = qVariantValue<QObject*>( sourceModel()->data( left, Kopete::Items::ObjectRole ) );
85  QObject* groupObjectRight = qVariantValue<QObject*>( sourceModel()->data( right, Kopete::Items::ObjectRole ) );
86 
87  if ( groupObjectLeft == Kopete::Group::offline() )
88  return false;
89  else if ( groupObjectRight == Kopete::Group::offline() )
90  return true;
91  return QString::localeAwareCompare( leftName, rightName ) < 0;
92  }
93  }
94  else if ( leftType == Kopete::Items::MetaContact )
95  {
96  switch ( Kopete::AppearanceSettings::self()->contactListMetaContactSorting() )
97  {
98  case Kopete::AppearanceSettings::EnumContactListMetaContactSorting::Manual:
99  return left.row() < right.row();
100  case Kopete::AppearanceSettings::EnumContactListMetaContactSorting::Status:
101  {
102  int leftStatus = left.data( Kopete::Items::OnlineStatusRole ).toInt();
103  int rightStatus = right.data( Kopete::Items::OnlineStatusRole ).toInt();
104  if ( leftStatus != rightStatus )
105  {
106  return !(leftStatus < rightStatus);
107  }
108  else
109  {
110  QString leftName = left.data( Qt::DisplayRole ).toString();
111  QString rightName = right.data( Qt::DisplayRole ).toString();
112  return (QString::localeAwareCompare( leftName, rightName ) < 0);
113  }
114  }
115  case Kopete::AppearanceSettings::EnumContactListMetaContactSorting::Name:
116  default:
117  QString leftName = left.data( Qt::DisplayRole ).toString();
118  QString rightName = right.data( Qt::DisplayRole ).toString();
119  return (QString::localeAwareCompare( leftName, rightName ) < 0);
120  }
121  }
122 
123  return false;
124 }
125 
126 bool ContactListProxyModel::filterAcceptsRow ( int sourceRow, const QModelIndex & sourceParent ) const
127 {
128  QAbstractItemModel* model = sourceModel();
129  QModelIndex current = model->index(sourceRow, 0, sourceParent);
130  bool showEmpty = Kopete::AppearanceSettings::self()->showEmptyGroups();
131  bool showOffline = Kopete::AppearanceSettings::self()->showOfflineUsers();
132 
133  if ( model->data( current, Kopete::Items::TypeRole ) == Kopete::Items::Group )
134  {
135  QObject* groupObject = qVariantValue<QObject*>( model->data( current, Kopete::Items::ObjectRole ) );
136  if ( qobject_cast<Kopete::Group*>(groupObject) == Kopete::Group::topLevel() )
137  return true;
138 
139  int connectedContactsCount = model->data( current, Kopete::Items::ConnectedCountRole ).toInt();
140  int totalContactsCount = model->data( current, Kopete::Items::TotalCountRole ).toInt();
141 
142  bool isOfflineGroup = ( groupObject == Kopete::Group::offline() );
143  if ( !filterRegExp().isEmpty() && isOfflineGroup )
144  return false;
145 
146  if ( !filterRegExp().isEmpty() )
147  {
148  // This shows or hides the contacts group folder if something was found.
149  // Walk through the group's metacontacts and see it the search result was found
150  // If it is found then we can show this group folder.
151  // This is fairly slow with > group 10000 contacts. Reasonable? (ginge)
152  for ( int i = 0; i < model->rowCount( current ); i++ )
153  {
154  QModelIndex qmi = model->index( i, 0, current );
155 
156  if ( model->data( qmi, Kopete::Items::TypeRole ) != Kopete::Items::MetaContact )
157  continue;
158 
159  QObject* mcObject = qVariantValue<QObject*>( model->data( qmi, Kopete::Items::ObjectRole ) );
160  Kopete::MetaContact *mc = qobject_cast<Kopete::MetaContact*>( mcObject );
161 
162  // Do a better search.
163  if ( searchContactInfo( mc, filterRegExp() ) )
164  {
165  qobject_cast<Kopete::Group*>(groupObject)->setExpanded(true);
166  return true;
167  }
168  }
169 
170  return false;
171  }
172 
173 
174  if ( !Kopete::AppearanceSettings::self()->showOfflineGrouped() && isOfflineGroup )
175  return false;
176 
177  if ( !showEmpty && totalContactsCount == 0 && !isOfflineGroup)
178  return false;
179 
180  // do not display offline when viewing in grouped offline mode
181  if ( showOffline && isOfflineGroup )
182  return false;
183 
184  if ( !showEmpty && !showOffline && connectedContactsCount == 0 && !isOfflineGroup )
185  return false;
186 
187  return true;
188  }
189 
190  if ( model->data( current, Kopete::Items::TypeRole ) == Kopete::Items::MetaContact )
191  {
192  if ( !filterRegExp().isEmpty() )
193  {
194  QObject* contactObject = qVariantValue<QObject*>( model->data( current, Kopete::Items::ObjectRole ) );
195  Kopete::MetaContact *mc = qobject_cast<Kopete::MetaContact*>(contactObject);
196 
197  // Do a better search
198  return searchContactInfo( mc, filterRegExp() );
199  }
200 
201  // Get the MetaContacts parent group name
202  QObject* groupObject = qVariantValue<QObject*>( model->data( sourceParent, Kopete::Items::ObjectRole ) );
203 
204  if ( Kopete::AppearanceSettings::self()->groupContactByGroup() && qobject_cast<Kopete::Group*>(groupObject) != 0 )
205  {
206  // If this contact's group is called Offline, and we are not globally
207  // showing offline all users show the offline group folder
208  if ( groupObject == Kopete::Group::offline() )
209  return !showOffline;
210  }
211 
212  bool alwaysVisible = model->data( current, Kopete::Items::AlwaysVisible ).toBool();
213  int mcStatus = model->data( current, Kopete::Items::OnlineStatusRole ).toInt();
214  if ( mcStatus <= OnlineStatus::Offline && !showOffline && !alwaysVisible )
215  return false;
216  else
217  return true;
218  }
219 
220  return false;
221 }
222 
223 void ContactListProxyModel::proxyRowsInserted( const QModelIndex& parent, int start, int end )
224 {
225  if (parent.isValid())
226  return;
227 
228  int count = (end - start) + 1;
229  if (rootRowCount <= 0 && count > 0 && !sortScheduled)
230  {
231  sortScheduled = true;
232  QTimer::singleShot( 0, this, SLOT(forceSort()) );
233  }
234  rootRowCount += count;
235 }
236 
237 void ContactListProxyModel::proxyRowsRemoved( const QModelIndex& parent, int start, int end )
238 {
239  if (parent.isValid())
240  return;
241 
242  int count = (end - start) + 1;
243  rootRowCount -= count;
244 }
245 
246 void ContactListProxyModel::proxyCheckSort()
247 {
248  int count = rowCount();
249  if (rootRowCount <= 0 && count > 0 && !sortScheduled)
250  {
251  sortScheduled = true;
252  QTimer::singleShot( 0, this, SLOT(forceSort()) );
253  }
254  rootRowCount = count;
255 }
256 
257 void ContactListProxyModel::forceSort()
258 {
259  if (!sortScheduled)
260  return;
261 
262  sortScheduled = false;
263  sort( -1, Qt::AscendingOrder );
264  sort( 0, Qt::AscendingOrder );
265 }
266 
267 // Better search. Now a search will look in the metacontact display name, the invidual account contact names and any email addresses.
268 bool ContactListProxyModel::searchContactInfo(Kopete::MetaContact *mc, QRegExp searchPattern) const
269 {
270  // Check the display name
271  if ( mc->displayName().contains( searchPattern ) )
272  return true;
273 
274  // Check the address book
275  KABC::Addressee addressee = KABC::StdAddressBook::self()->findByUid( mc->kabcId() );
276  if ( !addressee.isEmpty() )
277  {
278  QString emailAddr = addressee.fullEmail();
279 
280  if ( emailAddr.contains( searchPattern ) )
281  return true;
282  }
283 
284  // Check alternative names
285  foreach( Kopete::Contact* c , mc->contacts() )
286  {
287  // Search each metacontacts' contacts
288  if ( c->contactId().contains( searchPattern ) )
289  return true;
290  }
291 
292  return false;
293 }
294 
295 }
296 
297 }
298 
299 #include "contactlistproxymodel.moc"
QSortFilterProxyModel::invalidate
void invalidate()
QModelIndex
QAbstractItemModel::rowCount
virtual int rowCount(const QModelIndex &parent) const =0
contactlistproxymodel.h
QAbstractItemModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const =0
QString::localeAwareCompare
int localeAwareCompare(const QString &other) const
QAbstractItemModel::layoutChanged
void layoutChanged()
QSortFilterProxyModel::sort
virtual void sort(int column, Qt::SortOrder order)
QRegExp::isEmpty
bool isEmpty() const
kopeteitembase.h
Contains definitions common between model items.
Kopete::UI::ContactListProxyModel::rootRowCount
int rootRowCount
Definition: contactlistproxymodel.h:50
Kopete::UI::ContactListProxyModel::showOffline
bool showOffline
Definition: contactlistproxymodel.h:48
Kopete::Items::TotalCountRole
const int TotalCountRole
Definition: kopeteitembase.h:39
Kopete::Items::OnlineStatusRole
const int OnlineStatusRole
Definition: kopeteitembase.h:36
QAbstractItemModel::modelReset
void modelReset()
QSortFilterProxyModel::rowCount
virtual int rowCount(const QModelIndex &parent) const
Kopete::UI::ContactListProxyModel::filterAcceptsRow
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
Definition: contactlistproxymodel.cpp:126
QRegExp
Kopete::Items::MetaContact
Definition: kopeteitembase.h:57
QModelIndex::isValid
bool isValid() const
Kopete::Items::Group
Definition: kopeteitembase.h:57
QVariant::toInt
int toInt(bool *ok) const
Kopete::UI::ContactListProxyModel::sortScheduled
bool sortScheduled
Definition: contactlistproxymodel.h:51
QObject
QModelIndex::row
int row() const
Kopete::Items::TypeRole
const int TypeRole
Qt Model Role Definitions.
Definition: kopeteitembase.h:34
QSortFilterProxyModel::setDynamicSortFilter
void setDynamicSortFilter(bool enable)
QAbstractItemModel::data
virtual QVariant data(const QModelIndex &index, int role) const =0
QString
QAbstractItemModel::rowsRemoved
void rowsRemoved(const QModelIndex &parent, int start, int end)
Kopete::Items::AlwaysVisible
const int AlwaysVisible
Definition: kopeteitembase.h:54
QString::contains
bool contains(QChar ch, Qt::CaseSensitivity cs) const
QSortFilterProxyModel
Kopete::Items::ConnectedCountRole
const int ConnectedCountRole
Definition: kopeteitembase.h:40
QAbstractProxyModel::sourceModel
QAbstractItemModel * sourceModel() const
QModelIndex::data
QVariant data(int role) const
QVariant::toBool
bool toBool() const
QAbstractItemModel
Kopete::Items::ObjectRole
const int ObjectRole
Definition: kopeteitembase.h:50
QAbstractItemModel::rowsInserted
void rowsInserted(const QModelIndex &parent, int start, int end)
Kopete::UI::ContactListProxyModel::ContactListProxyModel
ContactListProxyModel(QObject *parent=0)
Definition: contactlistproxymodel.cpp:36
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Kopete::UI::ContactListProxyModel::slotConfigChanged
void slotConfigChanged()
Definition: contactlistproxymodel.cpp:60
QVariant::toString
QString toString() const
Kopete::UI::ContactListProxyModel::~ContactListProxyModel
~ContactListProxyModel()
Definition: contactlistproxymodel.cpp:55
Kopete::UI::ContactListProxyModel::lessThan
bool lessThan(const QModelIndex &left, const QModelIndex &right) const
Definition: contactlistproxymodel.cpp:66
QSortFilterProxyModel::filterRegExp
QRegExp filterRegExp() const
QTimer::singleShot
singleShot
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