2
* Copyright 2011 Intel Corporation.
3
* Copyright 2011 Robin Burchell
5
* This program is licensed under the terms and conditions of the
6
* Apache License, version 2.0. The full text of the Apache License is at
7
* http://www.apache.org/licenses/LICENSE-2.0
12
#include <QStringList>
14
#include "localeutils_p.h"
15
#include "seasideperson.h"
16
#include "seasidepeoplemodel.h"
17
#include "seasideproxymodel.h"
19
class SeasideProxyModelPriv
22
SeasideProxyModelPriv()
23
: componentComplete(false)
27
SeasideProxyModel::FilterType filterType;
28
LocaleUtils *localeHelper;
29
QString searchPattern;
30
bool componentComplete;
33
SeasideProxyModel::SeasideProxyModel(QObject *parent)
36
priv = new SeasideProxyModelPriv;
37
priv->filterType = FilterAll;
38
mDisplayLabelOrder = FirstNameFirst;
39
priv->localeHelper = LocaleUtils::self();
40
setDynamicSortFilter(true);
41
setFilterKeyColumn(-1);
43
connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)),
44
SIGNAL(countChanged()));
46
connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)),
47
SIGNAL(countChanged()));
49
connect(this, SIGNAL(layoutChanged()),
50
SIGNAL(countChanged()));
54
SeasideProxyModel::~SeasideProxyModel()
59
void SeasideProxyModel::classBegin()
61
priv->componentComplete = false;
64
void SeasideProxyModel::componentComplete()
66
priv->componentComplete = true;
68
SeasidePeopleModel *sourceModel = SeasidePeopleModel::instance();
69
setSourceModel(sourceModel);
70
sort(0, Qt::AscendingOrder);
72
connect(sourceModel, SIGNAL(populatedChanged()),
73
this, SIGNAL(populatedChanged()));
75
connect(this, SIGNAL(displayLabelOrderChanged(SeasideProxyModel::DisplayLabelOrder)),
76
sourceModel, SIGNAL(displayLabelOrderChanged(SeasideProxyModel::DisplayLabelOrder)));
78
if (mDisplayLabelOrder != FirstNameFirst) {
79
emit displayLabelOrderChanged(mDisplayLabelOrder);
83
bool SeasideProxyModel::populated() const
85
SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
87
return model->populated();
91
SeasideProxyModel::FilterType SeasideProxyModel::filterType() const
93
return priv->filterType;
96
void SeasideProxyModel::setFilter(FilterType filter)
98
if (filter != priv->filterType) {
99
priv->filterType = filter;
100
if (filter == FilterNone)
101
priv->searchPattern = QString();
102
if (priv->componentComplete)
104
emit filterTypeChanged();
105
if (filter == FilterNone)
106
emit filterPatternChanged();
110
QString SeasideProxyModel::filterPattern() const
112
return priv->searchPattern;
115
void SeasideProxyModel::setFilterPattern(const QString &pattern)
117
if (pattern != priv->searchPattern) {
118
priv->searchPattern = pattern;
119
if (priv->componentComplete)
121
emit filterPatternChanged();
125
SeasideProxyModel::DisplayLabelOrder SeasideProxyModel::displayLabelOrder()
127
return mDisplayLabelOrder;
130
void SeasideProxyModel::setDisplayLabelOrder(DisplayLabelOrder order)
132
if (order != mDisplayLabelOrder) {
133
mDisplayLabelOrder = order;
135
emit displayLabelOrderChanged(order);
139
bool SeasideProxyModel::personMatchesFilter(SeasidePerson *person, const QString &filter)
141
// split the display label and filter into words.
143
// TODO: i18n will require different splitting for thai and possibly
144
// other locales, see MBreakIterator
145
QStringList labelList = person->displayLabel().split(" ");
146
QStringList filterList = filter.split(" ");
148
// search forwards over the label components for each filter word, making
149
// sure to find all filter words before considering it a match.
151
// TODO: for performance, we may want to consider keeping a cached
152
// version of the parts comprising a display label -
153
// QStringList SeasidePerson::displayLabelParts?
155
for (int i = 0; i < filterList.size(); i++) {
157
for (; j < labelList.size(); j++) {
158
// TODO: for good i18n, we need to search insensitively taking
159
// diacritics into account, QString's functions alone aren't good
161
if (labelList.at(j).startsWith(filterList.at(i), Qt::CaseInsensitive)) {
168
// if the current filter word wasn't found in the search
169
// string, then it wasn't a match. we require all words
178
bool SeasideProxyModel::filterAcceptsRow(int source_row,
179
const QModelIndex& source_parent) const
181
// TODO: add communication history
182
//if (!QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent))
185
// TODO: it may be better to filter this in SeasidePeopleModel, instead
186
// of constantly doing it on refilter.
187
SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
188
SeasidePerson *person = model->personByRow(source_row);
189
if (person->id() == model->manager()->selfContactId())
192
if (!priv->searchPattern.isEmpty()) {
193
if (!personMatchesFilter(person, priv->searchPattern))
197
switch (priv->filterType) {
202
case FilterFavorites:
203
return person->favorite();
209
bool SeasideProxyModel::lessThan(const QModelIndex& left,
210
const QModelIndex& right) const
212
SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
214
SeasidePerson *leftPerson = model->personByRow(left.row());
215
SeasidePerson *rightPerson = model->personByRow(right.row());
219
else if (!rightPerson)
222
return priv->localeHelper->isLessThan(leftPerson->displayLabel(),
223
rightPerson->displayLabel());
226
QVariantMap SeasideProxyModel::get(int row) const
228
// needed for SectionScroller.
230
SeasidePerson *p = personByRow(row);
231
m["sectionBucket"] = p->sectionBucket();
235
bool SeasideProxyModel::savePerson(SeasidePerson *person)
237
SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
238
return model->savePerson(person);
241
SeasidePerson* SeasideProxyModel::personByRow(int row) const {
242
SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
243
int sourceRow = mapToSource(index(row, 0)).row();
244
return model->personByRow(sourceRow);
247
SeasidePerson * SeasideProxyModel::personById(int id) const
249
SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
250
return model->personById(id);
252
SeasidePerson * SeasideProxyModel::personByPhoneNumber(const QString &msisdn) const
254
SeasidePeopleModel *model = static_cast<SeasidePeopleModel*>(sourceModel());
255
return model->personByPhoneNumber(msisdn);
257
SeasidePerson * SeasideProxyModel::selfPerson() const
259
SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
260
return model->selfPerson();
262
void SeasideProxyModel::removePerson(SeasidePerson *person)
264
SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
265
model->removePerson(person);
268
int SeasideProxyModel::importContacts(const QString &path)
270
SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
271
return model->importContacts(path);
274
QString SeasideProxyModel::exportContacts()
276
SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
277
return model->exportContacts();
280
int SeasideProxyModel::count() const
282
return rowCount(QModelIndex());