~ubuntu-filemanager-dev/ubuntu-filemanager-app/nemo-qml-plugins-packaging

« back to all changes in this revision

Viewing changes to contacts/src/seasideproxymodel.cpp

  • Committer: Timo Jyrinki
  • Date: 2013-03-20 15:03:31 UTC
  • Revision ID: timo.jyrinki@canonical.com-20130320150331-aggtqfb7cufdiuzc
ImportĀ upstreamĀ 0.3.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2011 Intel Corporation.
 
3
 * Copyright 2011 Robin Burchell
 
4
 *
 
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
 
8
 */
 
9
 
 
10
#include <QDebug>
 
11
 
 
12
#include <QStringList>
 
13
 
 
14
#include "localeutils_p.h"
 
15
#include "seasideperson.h"
 
16
#include "seasidepeoplemodel.h"
 
17
#include "seasideproxymodel.h"
 
18
 
 
19
class SeasideProxyModelPriv
 
20
{
 
21
public:
 
22
    SeasideProxyModelPriv()
 
23
        : componentComplete(false)
 
24
    {
 
25
    }
 
26
 
 
27
    SeasideProxyModel::FilterType filterType;
 
28
    LocaleUtils *localeHelper;
 
29
    QString searchPattern;
 
30
    bool componentComplete;
 
31
};
 
32
 
 
33
SeasideProxyModel::SeasideProxyModel(QObject *parent)
 
34
{
 
35
    Q_UNUSED(parent);
 
36
    priv = new SeasideProxyModelPriv;
 
37
    priv->filterType = FilterAll;
 
38
    mDisplayLabelOrder = FirstNameFirst;
 
39
    priv->localeHelper = LocaleUtils::self();
 
40
    setDynamicSortFilter(true);
 
41
    setFilterKeyColumn(-1);
 
42
 
 
43
    connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)),
 
44
            SIGNAL(countChanged()));
 
45
 
 
46
    connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)),
 
47
            SIGNAL(countChanged()));
 
48
 
 
49
    connect(this, SIGNAL(layoutChanged()),
 
50
            SIGNAL(countChanged()));       
 
51
 
 
52
}
 
53
 
 
54
SeasideProxyModel::~SeasideProxyModel()
 
55
{
 
56
    delete priv;
 
57
}
 
58
 
 
59
void SeasideProxyModel::classBegin()
 
60
{
 
61
    priv->componentComplete = false;
 
62
}
 
63
 
 
64
void SeasideProxyModel::componentComplete()
 
65
{
 
66
    priv->componentComplete = true;
 
67
 
 
68
    SeasidePeopleModel *sourceModel = SeasidePeopleModel::instance();
 
69
    setSourceModel(sourceModel);
 
70
    sort(0, Qt::AscendingOrder);
 
71
 
 
72
    connect(sourceModel, SIGNAL(populatedChanged()),
 
73
            this, SIGNAL(populatedChanged()));
 
74
 
 
75
    connect(this, SIGNAL(displayLabelOrderChanged(SeasideProxyModel::DisplayLabelOrder)),
 
76
            sourceModel, SIGNAL(displayLabelOrderChanged(SeasideProxyModel::DisplayLabelOrder)));
 
77
 
 
78
    if (mDisplayLabelOrder != FirstNameFirst) {
 
79
        emit displayLabelOrderChanged(mDisplayLabelOrder);
 
80
    }
 
81
}
 
82
 
 
83
bool SeasideProxyModel::populated() const
 
84
{
 
85
    SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
 
86
    if (model)
 
87
        return model->populated();
 
88
    return false;
 
89
}
 
90
 
 
91
SeasideProxyModel::FilterType SeasideProxyModel::filterType() const
 
92
{
 
93
    return priv->filterType;
 
94
}
 
95
 
 
96
void SeasideProxyModel::setFilter(FilterType filter)
 
97
{
 
98
    if (filter != priv->filterType) {
 
99
        priv->filterType = filter;
 
100
        if (filter == FilterNone)
 
101
            priv->searchPattern = QString();
 
102
        if (priv->componentComplete)
 
103
            invalidateFilter();
 
104
        emit filterTypeChanged();
 
105
        if (filter == FilterNone)
 
106
            emit filterPatternChanged();
 
107
    }
 
108
}
 
109
 
 
110
QString SeasideProxyModel::filterPattern() const
 
111
{
 
112
    return priv->searchPattern;
 
113
}
 
114
 
 
115
void SeasideProxyModel::setFilterPattern(const QString &pattern)
 
116
{
 
117
    if (pattern != priv->searchPattern) {
 
118
        priv->searchPattern = pattern;
 
119
        if (priv->componentComplete)
 
120
            invalidateFilter();
 
121
        emit filterPatternChanged();
 
122
    }
 
123
}
 
124
 
 
125
SeasideProxyModel::DisplayLabelOrder SeasideProxyModel::displayLabelOrder()
 
126
{
 
127
    return mDisplayLabelOrder;
 
128
}
 
129
 
 
130
void SeasideProxyModel::setDisplayLabelOrder(DisplayLabelOrder order)
 
131
{
 
132
    if (order != mDisplayLabelOrder) {
 
133
        mDisplayLabelOrder = order;
 
134
        invalidate();
 
135
        emit displayLabelOrderChanged(order);
 
136
    }
 
137
}
 
138
 
 
139
bool SeasideProxyModel::personMatchesFilter(SeasidePerson *person, const QString &filter)
 
140
{
 
141
    // split the display label and filter into words.
 
142
    //
 
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(" ");
 
147
 
 
148
    // search forwards over the label components for each filter word, making
 
149
    // sure to find all filter words before considering it a match.
 
150
    //
 
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?
 
154
    int j = 0;
 
155
    for (int i = 0; i < filterList.size(); i++) {
 
156
        bool found = false;
 
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
 
160
            // enough
 
161
            if (labelList.at(j).startsWith(filterList.at(i), Qt::CaseInsensitive)) {
 
162
                found = true;
 
163
                j++;
 
164
                break;
 
165
            }
 
166
        }
 
167
 
 
168
        // if the current filter word wasn't found in the search
 
169
        // string, then it wasn't a match. we require all words
 
170
        // to match.
 
171
        if (!found)
 
172
            return false;
 
173
    }
 
174
 
 
175
    return true;
 
176
}
 
177
 
 
178
bool SeasideProxyModel::filterAcceptsRow(int source_row,
 
179
                                  const QModelIndex& source_parent) const
 
180
{
 
181
    // TODO: add communication history
 
182
    //if (!QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent))
 
183
    //    return false;
 
184
 
 
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())
 
190
        return false;
 
191
 
 
192
    if (!priv->searchPattern.isEmpty()) {
 
193
        if (!personMatchesFilter(person, priv->searchPattern))
 
194
            return false;
 
195
    }
 
196
 
 
197
    switch (priv->filterType) {
 
198
        case FilterNone:
 
199
            return false;
 
200
        case FilterAll:
 
201
            return true;
 
202
        case FilterFavorites:
 
203
            return person->favorite();
 
204
    }
 
205
 
 
206
    return false;
 
207
}
 
208
 
 
209
bool SeasideProxyModel::lessThan(const QModelIndex& left,
 
210
                                 const QModelIndex& right) const
 
211
{
 
212
    SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
 
213
 
 
214
    SeasidePerson *leftPerson = model->personByRow(left.row());
 
215
    SeasidePerson *rightPerson = model->personByRow(right.row());
 
216
 
 
217
    if (!leftPerson)
 
218
        return false;
 
219
    else if (!rightPerson)
 
220
        return true;
 
221
 
 
222
    return priv->localeHelper->isLessThan(leftPerson->displayLabel(),
 
223
                                          rightPerson->displayLabel());
 
224
}
 
225
 
 
226
QVariantMap SeasideProxyModel::get(int row) const
 
227
{
 
228
    // needed for SectionScroller.
 
229
    QVariantMap m;
 
230
    SeasidePerson *p = personByRow(row);
 
231
    m["sectionBucket"] = p->sectionBucket();
 
232
    return m;
 
233
}
 
234
 
 
235
bool SeasideProxyModel::savePerson(SeasidePerson *person)
 
236
{
 
237
    SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
 
238
    return model->savePerson(person);
 
239
}
 
240
 
 
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);
 
245
}
 
246
 
 
247
SeasidePerson * SeasideProxyModel::personById(int id) const
 
248
{
 
249
    SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
 
250
    return model->personById(id);
 
251
}
 
252
SeasidePerson * SeasideProxyModel::personByPhoneNumber(const QString &msisdn) const
 
253
{
 
254
    SeasidePeopleModel *model = static_cast<SeasidePeopleModel*>(sourceModel());
 
255
    return model->personByPhoneNumber(msisdn);
 
256
}
 
257
SeasidePerson * SeasideProxyModel::selfPerson() const
 
258
{
 
259
    SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
 
260
    return model->selfPerson();
 
261
}
 
262
void SeasideProxyModel::removePerson(SeasidePerson *person)
 
263
{
 
264
    SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
 
265
    model->removePerson(person);
 
266
}
 
267
 
 
268
int SeasideProxyModel::importContacts(const QString &path)
 
269
{
 
270
    SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
 
271
    return model->importContacts(path);
 
272
}
 
273
 
 
274
QString SeasideProxyModel::exportContacts()
 
275
{
 
276
    SeasidePeopleModel *model = static_cast<SeasidePeopleModel *>(sourceModel());
 
277
    return model->exportContacts();
 
278
}
 
279
 
 
280
int SeasideProxyModel::count() const
 
281
{
 
282
    return rowCount(QModelIndex());
 
283
}