Merge lp:~bfiller/history-service/rtm-14.09-sim-presence into lp:history-service/rtm-14.09

Proposed by Bill Filler
Status: Merged
Approved by: Bill Filler
Approved revision: 164
Merged at revision: 164
Proposed branch: lp:~bfiller/history-service/rtm-14.09-sim-presence
Merge into: lp:history-service/rtm-14.09
Diff against target: 884 lines (+517/-56)
11 files modified
Ubuntu/History/CMakeLists.txt (+2/-0)
Ubuntu/History/historyeventmodel.cpp (+34/-20)
Ubuntu/History/historyeventmodel.h (+18/-14)
Ubuntu/History/historygroupedeventsmodel.cpp (+346/-0)
Ubuntu/History/historygroupedeventsmodel.h (+82/-0)
Ubuntu/History/historyqmlplugin.cpp (+2/-0)
Ubuntu/History/historythreadmodel.cpp (+23/-21)
Ubuntu/History/historythreadmodel.h (+2/-1)
src/event.cpp (+6/-0)
src/event.h (+1/-0)
src/types.h (+1/-0)
To merge this branch: bzr merge lp:~bfiller/history-service/rtm-14.09-sim-presence
Reviewer Review Type Date Requested Status
Ubuntu Phablet Team Pending
Review via email: mp+231916@code.launchpad.net

Commit message

sim presence and call grouping merge from trunk

Description of the change

sim presence and call grouping merge from trunk

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Ubuntu/History/CMakeLists.txt'
--- Ubuntu/History/CMakeLists.txt 2014-07-14 23:05:23 +0000
+++ Ubuntu/History/CMakeLists.txt 2014-08-22 15:31:10 +0000
@@ -2,6 +2,7 @@
22
3set(plugin_SRCS3set(plugin_SRCS
4 historyeventmodel.cpp4 historyeventmodel.cpp
5 historygroupedeventsmodel.cpp
5 historythreadgroupingproxymodel.cpp6 historythreadgroupingproxymodel.cpp
6 historyqmltexteventattachment.cpp7 historyqmltexteventattachment.cpp
7 historyqmlfilter.cpp8 historyqmlfilter.cpp
@@ -15,6 +16,7 @@
1516
16set(plugin_HDRS17set(plugin_HDRS
17 historyeventmodel.h18 historyeventmodel.h
19 historygroupedeventsmodel.h
18 historythreadgroupingproxymodel.h20 historythreadgroupingproxymodel.h
19 historyqmltexteventattachment.h21 historyqmltexteventattachment.h
20 historyqmlfilter.h22 historyqmlfilter.h
2123
=== modified file 'Ubuntu/History/historyeventmodel.cpp'
--- Ubuntu/History/historyeventmodel.cpp 2014-08-07 19:22:31 +0000
+++ Ubuntu/History/historyeventmodel.cpp 2014-08-22 15:31:10 +0000
@@ -37,7 +37,8 @@
3737
38HistoryEventModel::HistoryEventModel(QObject *parent) :38HistoryEventModel::HistoryEventModel(QObject *parent) :
39 QAbstractListModel(parent), mCanFetchMore(true), mFilter(0),39 QAbstractListModel(parent), mCanFetchMore(true), mFilter(0),
40 mSort(0), mType(HistoryThreadModel::EventTypeText), mEventWritingTimer(0), mFetchTimer(0)40 mSort(new HistoryQmlSort(this)), mType(HistoryThreadModel::EventTypeText),
41 mEventWritingTimer(0), mUpdateTimer(0)
41{42{
42 connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SIGNAL(countChanged()));43 connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SIGNAL(countChanged()));
43 connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SIGNAL(countChanged()));44 connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SIGNAL(countChanged()));
@@ -63,7 +64,7 @@
63 mRoles[CallDurationRole] = "callDuration";64 mRoles[CallDurationRole] = "callDuration";
6465
65 // create the view and get some objects66 // create the view and get some objects
66 updateQuery();67 triggerQueryUpdate();
67}68}
6869
69int HistoryEventModel::rowCount(const QModelIndex &parent) const70int HistoryEventModel::rowCount(const QModelIndex &parent) const
@@ -81,7 +82,11 @@
81 return QVariant();82 return QVariant();
82 }83 }
8384
84 History::Event event = mEvents[index.row()];85 return eventData(mEvents[index.row()], role);
86}
87
88QVariant HistoryEventModel::eventData(const History::Event &event, int role) const
89{
85 History::TextEvent textEvent;90 History::TextEvent textEvent;
86 History::VoiceEvent voiceEvent;91 History::VoiceEvent voiceEvent;
87 History::Thread thread;92 History::Thread thread;
@@ -194,7 +199,7 @@
194 return;199 return;
195 }200 }
196201
197 History::Events events = mView->nextPage();202 History::Events events = fetchNextPage();
198203
199 qDebug() << "Got events:" << events.count();204 qDebug() << "Got events:" << events.count();
200 if (events.isEmpty()) {205 if (events.isEmpty()) {
@@ -227,11 +232,11 @@
227 if (mFilter) {232 if (mFilter) {
228 connect(mFilter,233 connect(mFilter,
229 SIGNAL(filterChanged()),234 SIGNAL(filterChanged()),
230 SLOT(updateQuery()));235 SLOT(triggerQueryUpdate()));
231 }236 }
232237
233 Q_EMIT filterChanged();238 Q_EMIT filterChanged();
234 updateQuery();239 triggerQueryUpdate();
235}240}
236241
237HistoryQmlSort *HistoryEventModel::sort() const242HistoryQmlSort *HistoryEventModel::sort() const
@@ -250,11 +255,11 @@
250 if (mSort) {255 if (mSort) {
251 connect(mSort,256 connect(mSort,
252 SIGNAL(sortChanged()),257 SIGNAL(sortChanged()),
253 SLOT(updateQuery()));258 SLOT(triggerQueryUpdate()));
254 }259 }
255260
256 Q_EMIT sortChanged();261 Q_EMIT sortChanged();
257 updateQuery();262 triggerQueryUpdate();
258}263}
259264
260HistoryThreadModel::EventType HistoryEventModel::type() const265HistoryThreadModel::EventType HistoryEventModel::type() const
@@ -266,7 +271,7 @@
266{271{
267 mType = value;272 mType = value;
268 Q_EMIT typeChanged();273 Q_EMIT typeChanged();
269 updateQuery();274 triggerQueryUpdate();
270}275}
271276
272QString HistoryEventModel::threadIdForParticipants(const QString &accountId, int eventType, const QStringList &participants, int matchFlags, bool create)277QString HistoryEventModel::threadIdForParticipants(const QString &accountId, int eventType, const QStringList &participants, int matchFlags, bool create)
@@ -378,7 +383,7 @@
378 SLOT(onEventsRemoved(History::Events)));383 SLOT(onEventsRemoved(History::Events)));
379 connect(mView.data(),384 connect(mView.data(),
380 SIGNAL(invalidated()),385 SIGNAL(invalidated()),
381 SLOT(updateQuery()));386 SLOT(triggerQueryUpdate()));
382387
383 mCanFetchMore = true;388 mCanFetchMore = true;
384 Q_EMIT canFetchMoreChanged();389 Q_EMIT canFetchMoreChanged();
@@ -391,12 +396,7 @@
391 }396 }
392 mAttachmentCache.clear();397 mAttachmentCache.clear();
393398
394 if (mFetchTimer) {399 fetchMore(QModelIndex());
395 killTimer(mFetchTimer);
396 }
397
398 // delay the loading of the model data until the settings settle down
399 mFetchTimer = startTimer(100);
400}400}
401401
402void HistoryEventModel::onEventsAdded(const History::Events &events)402void HistoryEventModel::onEventsAdded(const History::Events &events)
@@ -474,13 +474,18 @@
474 qDebug() << "... succeeded!";474 qDebug() << "... succeeded!";
475 mEventWritingQueue.clear();475 mEventWritingQueue.clear();
476 }476 }
477 } else if (event->timerId() == mFetchTimer) {477 } else if (event->timerId() == mUpdateTimer) {
478 killTimer(mFetchTimer);478 killTimer(mUpdateTimer);
479 mFetchTimer = 0;479 mUpdateTimer = 0;
480 fetchMore(QModelIndex());480 updateQuery();
481 }481 }
482}482}
483483
484History::Events HistoryEventModel::fetchNextPage()
485{
486 return mView->nextPage();
487}
488
484QVariant HistoryEventModel::get(int row) const489QVariant HistoryEventModel::get(int row) const
485{490{
486 if (row >= this->rowCount() || row < 0) {491 if (row >= this->rowCount() || row < 0) {
@@ -489,3 +494,12 @@
489494
490 return QVariant(mEvents[row].properties());495 return QVariant(mEvents[row].properties());
491}496}
497
498void HistoryEventModel::triggerQueryUpdate()
499{
500 if (mUpdateTimer) {
501 killTimer(mUpdateTimer);
502 }
503 // delay the loading of the model data until the settings settle down
504 mUpdateTimer = startTimer(100);
505}
492506
=== modified file 'Ubuntu/History/historyeventmodel.h'
--- Ubuntu/History/historyeventmodel.h 2014-08-07 19:22:31 +0000
+++ Ubuntu/History/historyeventmodel.h 2014-08-22 15:31:10 +0000
@@ -53,18 +53,20 @@
53 TextReadSubjectRole,53 TextReadSubjectRole,
54 TextMessageAttachmentsRole,54 TextMessageAttachmentsRole,
55 CallMissedRole,55 CallMissedRole,
56 CallDurationRole56 CallDurationRole,
57 LastRole
57 };58 };
5859
59 explicit HistoryEventModel(QObject *parent = 0);60 explicit HistoryEventModel(QObject *parent = 0);
6061
61 int rowCount(const QModelIndex &parent = QModelIndex()) const;62 virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
62 QVariant data(const QModelIndex &index, int role) const;63 virtual QVariant data(const QModelIndex &index, int role) const;
6364 QVariant eventData(const History::Event &event, int role) const;
64 Q_INVOKABLE bool canFetchMore(const QModelIndex &parent = QModelIndex()) const;65
65 Q_INVOKABLE void fetchMore(const QModelIndex &parent = QModelIndex());66 Q_INVOKABLE virtual bool canFetchMore(const QModelIndex &parent = QModelIndex()) const;
6667 Q_INVOKABLE virtual void fetchMore(const QModelIndex &parent = QModelIndex());
67 QHash<int, QByteArray> roleNames() const;68
69 virtual QHash<int, QByteArray> roleNames() const;
6870
69 HistoryQmlFilter *filter() const;71 HistoryQmlFilter *filter() const;
70 void setFilter(HistoryQmlFilter *value);72 void setFilter(HistoryQmlFilter *value);
@@ -85,7 +87,7 @@
85 Q_INVOKABLE bool markEventAsRead(const QString &accountId, const QString &threadId, const QString &eventId, int eventType);87 Q_INVOKABLE bool markEventAsRead(const QString &accountId, const QString &threadId, const QString &eventId, int eventType);
8688
87 Q_INVOKABLE bool removeEventAttachment(const QString &accountId, const QString &threadId, const QString &eventId, int eventType, const QString &attachmentId);89 Q_INVOKABLE bool removeEventAttachment(const QString &accountId, const QString &threadId, const QString &eventId, int eventType, const QString &attachmentId);
88 Q_INVOKABLE QVariant get(int row) const;90 Q_INVOKABLE virtual QVariant get(int row) const;
8991
90Q_SIGNALS:92Q_SIGNALS:
91 void countChanged();93 void countChanged();
@@ -95,13 +97,15 @@
95 void canFetchMoreChanged();97 void canFetchMoreChanged();
9698
97protected Q_SLOTS:99protected Q_SLOTS:
98 void updateQuery();100 void triggerQueryUpdate();
99 void onEventsAdded(const History::Events &events);101 virtual void updateQuery();
100 void onEventsModified(const History::Events &events);102 virtual void onEventsAdded(const History::Events &events);
101 void onEventsRemoved(const History::Events &events);103 virtual void onEventsModified(const History::Events &events);
104 virtual void onEventsRemoved(const History::Events &events);
102105
103protected:106protected:
104 void timerEvent(QTimerEvent *event);107 void timerEvent(QTimerEvent *event);
108 History::Events fetchNextPage();
105109
106private:110private:
107 History::EventViewPtr mView;111 History::EventViewPtr mView;
@@ -114,7 +118,7 @@
114 mutable QMap<History::TextEvent, QList<QVariant> > mAttachmentCache;118 mutable QMap<History::TextEvent, QList<QVariant> > mAttachmentCache;
115 History::Events mEventWritingQueue;119 History::Events mEventWritingQueue;
116 int mEventWritingTimer;120 int mEventWritingTimer;
117 int mFetchTimer;121 int mUpdateTimer;
118};122};
119123
120#endif // HISTORYEVENTMODEL_H124#endif // HISTORYEVENTMODEL_H
121125
=== added file 'Ubuntu/History/historygroupedeventsmodel.cpp'
--- Ubuntu/History/historygroupedeventsmodel.cpp 1970-01-01 00:00:00 +0000
+++ Ubuntu/History/historygroupedeventsmodel.cpp 2014-08-22 15:31:10 +0000
@@ -0,0 +1,346 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * Authors:
5 * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com>
6 *
7 * This file is part of history-service.
8 *
9 * history-service is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 3.
12 *
13 * history-service is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "historygroupedeventsmodel.h"
23#include "phoneutils_p.h"
24#include "sort.h"
25#include "historyqmlsort.h"
26
27HistoryGroupedEventsModel::HistoryGroupedEventsModel(QObject *parent) :
28 HistoryEventModel(parent)
29{
30}
31
32int HistoryGroupedEventsModel::rowCount(const QModelIndex &parent) const
33{
34 if (parent.isValid()) {
35 return 0;
36 }
37
38 return mEventGroups.count();
39}
40
41QVariant HistoryGroupedEventsModel::data(const QModelIndex &index, int role) const
42{
43 if (!index.isValid() || index.row() < 0 || index.row() >= mEventGroups.count()) {
44 return QVariant();
45 }
46
47 HistoryEventGroup group = mEventGroups[index.row()];
48 QVariant result;
49 QVariantList events;
50
51 switch (role) {
52 case EventsRole:
53 Q_FOREACH(const History::Event &event, group.events) {
54 events << event.properties();
55 }
56 result = events;
57 break;
58 case EventCountRole:
59 result = group.events.count();
60 break;
61 default:
62 result = eventData(group.displayedEvent, role);
63 break;
64 }
65
66 return result;
67}
68
69void HistoryGroupedEventsModel::fetchMore(const QModelIndex &parent)
70{
71 if (!canFetchMore(parent)) {
72 return;
73 }
74
75 History::Events events = fetchNextPage();
76
77 // History already deliver us the events in the right order
78 // but we might have added new entries in the added, removed, modified events.
79 // still, it is less expensive to do a sequential search starting from the bottom
80 // than to do a binary search for each event, as it is very likely that the entries
81 // belong to the bottom part of the model.
82 Q_FOREACH(const History::Event event, events) {
83 bool found = false;
84 int pos = mEventGroups.count() -1;
85 for (; pos >= 0; pos--) {
86 HistoryEventGroup &group = mEventGroups[pos];
87 if (areOfSameGroup(event, group.displayedEvent)) {
88 found = true;
89 addEventToGroup(event, group, pos);
90 break;
91 } else if (isAscending() ? lessThan(group.displayedEvent, event) : lessThan(event, group.displayedEvent)) {
92 break;
93 }
94 }
95
96 if (!found) {
97 // the item goes into a new group right after the position found above
98 pos++;
99 HistoryEventGroup group;
100 group.displayedEvent = event;
101 group.events << event;
102 beginInsertRows(QModelIndex(), pos, pos);
103 mEventGroups.insert(pos, group);
104 endInsertRows();
105 }
106 }
107}
108
109QHash<int, QByteArray> HistoryGroupedEventsModel::roleNames() const
110{
111 QHash<int, QByteArray> roles = HistoryEventModel::roleNames();
112 roles[EventsRole] = "events";
113 roles[EventCountRole] = "eventCount";
114 return roles;
115}
116
117void HistoryGroupedEventsModel::updateQuery()
118{
119 // remove all event groups from the model
120 if (!mEventGroups.isEmpty()) {
121 beginRemoveRows(QModelIndex(), 0, mEventGroups.count() - 1);
122 mEventGroups.clear();
123 endRemoveRows();
124 }
125
126 // and ask HistoryEventModel to update the query and fetch items again
127 HistoryEventModel::updateQuery();
128}
129
130void HistoryGroupedEventsModel::onEventsAdded(const History::Events &events)
131{
132 if (!events.count()) {
133 return;
134 }
135
136 Q_FOREACH(const History::Event &event, events) {
137 int pos = positionForEvent(event);
138
139 // check if the event belongs to the group at the position
140 if (pos >= 0 && pos < mEventGroups.count()) {
141 HistoryEventGroup &group = mEventGroups[pos];
142 if (areOfSameGroup(event, group.displayedEvent)) {
143 addEventToGroup(event, group, pos);
144 continue;
145 }
146 }
147
148 // else, we just create a new group
149 beginInsertRows(QModelIndex(), pos, pos);
150 HistoryEventGroup group;
151 group.displayedEvent = event;
152 group.events << event;
153 mEventGroups.insert(pos, group);
154 endInsertRows();
155
156 }
157}
158
159void HistoryGroupedEventsModel::onEventsModified(const History::Events &events)
160{
161 // FIXME: we are not yet handling events changing the property used for sorting
162 // so for now the behavior is to find the item and check if it needs inserting or
163 // updating in the group, which is exactly what onEventsAdded() does, so:
164 onEventsAdded(events);
165}
166
167void HistoryGroupedEventsModel::onEventsRemoved(const History::Events &events)
168{
169 Q_FOREACH(const History::Event &event, events) {
170 int pos = positionForEvent(event);
171 if (pos < 0 || pos >= rowCount()) {
172 continue;
173 }
174 HistoryEventGroup &group = mEventGroups[pos];
175 if (!group.events.contains(event)) {
176 continue;
177 }
178 removeEventFromGroup(event, group, pos);
179 }
180}
181
182bool HistoryGroupedEventsModel::compareParticipants(const QStringList &list1, const QStringList &list2)
183{
184 if (list1.count() != list2.count()) {
185 return false;
186 }
187
188 int found = 0;
189 Q_FOREACH(const QString &participant, list1) {
190 Q_FOREACH(const QString &item, list2) {
191 if (PhoneUtils::comparePhoneNumbers(participant, item)) {
192 found++;
193 break;
194 }
195 }
196 }
197
198 return found == list1.count();
199}
200
201bool HistoryGroupedEventsModel::areOfSameGroup(const History::Event &event1, const History::Event &event2)
202{
203 QVariantMap props1 = event1.properties();
204 QVariantMap props2 = event2.properties();
205
206 Q_FOREACH(const QString &property, mGroupingProperties) {
207 // first check if the property exists in the maps
208 if (!props1.contains(property) || !props2.contains(property)) {
209 return false;
210 }
211
212 // now check if the values are the same
213 if (property == History::FieldParticipants) {
214 if (!compareParticipants(props1[property].toStringList(),
215 props2[property].toStringList())) {
216 return false;
217 }
218 } else if (props1[property] != props2[property]) {
219 return false;
220 }
221 }
222
223 // if it didn't fail before, the events are indeed of the same group
224 return true;
225}
226
227void HistoryGroupedEventsModel::addEventToGroup(const History::Event &event, HistoryEventGroup &group, int row)
228{
229 if (!group.events.contains(event)) {
230 // insert the event in the correct position according to the sort criteria
231 bool append = true;
232 for (int i = 0; i < group.events.count(); ++i) {
233 History::Event &otherEvent = group.events[i];
234 if (isAscending() ? lessThan(event, otherEvent) : lessThan(otherEvent, event)) {
235 group.events.insert(i, event);
236 append = false;
237 break;
238 }
239 }
240
241 // if it is not above any item, just append it
242 if (append) {
243 group.events.append(event);
244 }
245 }
246
247 // now check if the displayed event should be updated
248 History::Event &firstEvent = group.events.first();
249 if (group.displayedEvent != firstEvent) {
250 group.displayedEvent = firstEvent;
251 QModelIndex idx(index(row));
252 Q_EMIT dataChanged(idx, idx);
253 }
254}
255
256void HistoryGroupedEventsModel::removeEventFromGroup(const History::Event &event, HistoryEventGroup &group, int row)
257{
258 if (group.events.contains(event)) {
259 group.events.removeOne(event);
260 }
261
262 if (group.events.isEmpty()) {
263 beginRemoveRows(QModelIndex(), row, row);
264 mEventGroups.removeAt(row);
265 endRemoveRows();
266 return;
267 }
268
269 if (group.displayedEvent == event) {
270 // check what is the event that should be displayed
271 group.displayedEvent = group.events.first();
272 Q_FOREACH(const History::Event &other, group.events) {
273 if (isAscending() ? lessThan(other, group.displayedEvent) : lessThan(group.displayedEvent, other)) {
274 group.displayedEvent = other;
275 }
276 }
277 }
278 QModelIndex idx = index(row);
279 Q_EMIT dataChanged(idx, idx);
280}
281
282bool HistoryGroupedEventsModel::lessThan(const History::Event &left, const History::Event &right) const
283{
284
285 QVariant leftValue = left.properties()[sort()->sortField()];
286 QVariant rightValue = right.properties()[sort()->sortField()];
287 return leftValue < rightValue;
288}
289
290int HistoryGroupedEventsModel::positionForEvent(const History::Event &event) const
291{
292 // do a binary search for the item position on the list
293 int lowerBound = 0;
294 int upperBound = mEventGroups.count() - 1;
295 if (upperBound < 0) {
296 return 0;
297 }
298
299 while (true) {
300 int pos = (upperBound + lowerBound) / 2;
301 const History::Event &posEvent = mEventGroups[pos].displayedEvent;
302 if (lowerBound == pos) {
303 if (isAscending() ? lessThan(event, posEvent) : lessThan(posEvent, event)) {
304 return pos;
305 }
306 }
307 if (isAscending() ? lessThan(posEvent, event) : lessThan(event, posEvent)) {
308 lowerBound = pos + 1; // its in the upper
309 if (lowerBound > upperBound) {
310 return pos += 1;
311 }
312 } else if (lowerBound > upperBound) {
313 return pos;
314 } else {
315 upperBound = pos - 1; // its in the lower
316 }
317 }
318
319}
320
321QVariant HistoryGroupedEventsModel::get(int row) const
322{
323 if (row >= rowCount() || row < 0) {
324 return QVariant();
325 }
326
327 return data(index(row), EventsRole);
328}
329
330
331QStringList HistoryGroupedEventsModel::groupingProperties() const
332{
333 return mGroupingProperties;
334}
335
336void HistoryGroupedEventsModel::setGroupingProperties(const QStringList &properties)
337{
338 mGroupingProperties = properties;
339 Q_EMIT groupingPropertiesChanged();
340 triggerQueryUpdate();
341}
342
343bool HistoryGroupedEventsModel::isAscending() const
344{
345 return sort() && sort()->sort().sortOrder() == Qt::AscendingOrder;
346}
0347
=== added file 'Ubuntu/History/historygroupedeventsmodel.h'
--- Ubuntu/History/historygroupedeventsmodel.h 1970-01-01 00:00:00 +0000
+++ Ubuntu/History/historygroupedeventsmodel.h 2014-08-22 15:31:10 +0000
@@ -0,0 +1,82 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * Authors:
5 * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com>
6 *
7 * This file is part of history-service.
8 *
9 * history-service is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 3.
12 *
13 * history-service is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#ifndef HISTORYGROUPEDEVENTSMODEL_H
23#define HISTORYGROUPEDEVENTSMODEL_H
24
25#include "historyeventmodel.h"
26
27typedef struct {
28 History::Events events;
29 History::Event displayedEvent;
30} HistoryEventGroup;
31
32class HistoryGroupedEventsModel : public HistoryEventModel
33{
34 Q_OBJECT
35 Q_PROPERTY(QStringList groupingProperties
36 READ groupingProperties
37 WRITE setGroupingProperties
38 NOTIFY groupingPropertiesChanged)
39 Q_ENUMS(GroupedRole)
40public:
41 enum GroupedRole {
42 EventsRole = HistoryEventModel::LastRole,
43 EventCountRole
44 };
45
46 explicit HistoryGroupedEventsModel(QObject *parent = 0);
47
48 // reimplemented from HistoryEventModel
49 int rowCount(const QModelIndex &parent = QModelIndex()) const;
50 QVariant data(const QModelIndex &index, int role) const;
51 Q_INVOKABLE void fetchMore(const QModelIndex &parent = QModelIndex());
52 QHash<int, QByteArray> roleNames() const;
53 Q_INVOKABLE QVariant get(int row) const;
54
55 QStringList groupingProperties() const;
56 void setGroupingProperties(const QStringList &properties);
57
58 bool isAscending() const;
59
60Q_SIGNALS:
61 void groupingPropertiesChanged();
62
63protected Q_SLOTS:
64 void updateQuery();
65 void onEventsAdded(const History::Events &events);
66 void onEventsModified(const History::Events &events);
67 void onEventsRemoved(const History::Events &events);
68
69protected:
70 bool compareParticipants(const QStringList &list1, const QStringList &list2);
71 bool areOfSameGroup(const History::Event &event1, const History::Event &event2);
72 void addEventToGroup(const History::Event &event, HistoryEventGroup &group, int row);
73 void removeEventFromGroup(const History::Event &event, HistoryEventGroup &group, int row);
74 bool lessThan(const History::Event &left, const History::Event &right) const;
75 int positionForEvent(const History::Event &event) const;
76
77private:
78 QStringList mGroupingProperties;
79 QList<HistoryEventGroup> mEventGroups;
80};
81
82#endif // HISTORYGROUPEDEVENTSMODEL_H
083
=== modified file 'Ubuntu/History/historyqmlplugin.cpp'
--- Ubuntu/History/historyqmlplugin.cpp 2014-07-14 23:05:23 +0000
+++ Ubuntu/History/historyqmlplugin.cpp 2014-08-22 15:31:10 +0000
@@ -27,6 +27,7 @@
27#include "historythreadmodel.h"27#include "historythreadmodel.h"
28#include "historythreadgroupingproxymodel.h"28#include "historythreadgroupingproxymodel.h"
29#include "historyeventmodel.h"29#include "historyeventmodel.h"
30#include "historygroupedeventsmodel.h"
30#include "historyqmltexteventattachment.h"31#include "historyqmltexteventattachment.h"
31#include "sortproxymodel.h"32#include "sortproxymodel.h"
32#include <QQmlEngine>33#include <QQmlEngine>
@@ -43,6 +44,7 @@
43{44{
44 // @uri History45 // @uri History
45 qmlRegisterType<HistoryEventModel>(uri, 0, 1, "HistoryEventModel");46 qmlRegisterType<HistoryEventModel>(uri, 0, 1, "HistoryEventModel");
47 qmlRegisterType<HistoryGroupedEventsModel>(uri, 0, 1, "HistoryGroupedEventsModel");
46 qmlRegisterType<HistoryThreadModel>(uri, 0, 1, "HistoryThreadModel");48 qmlRegisterType<HistoryThreadModel>(uri, 0, 1, "HistoryThreadModel");
47 qmlRegisterType<HistoryQmlFilter>(uri, 0, 1, "HistoryFilter");49 qmlRegisterType<HistoryQmlFilter>(uri, 0, 1, "HistoryFilter");
48 qmlRegisterType<HistoryQmlIntersectionFilter>(uri, 0, 1, "HistoryIntersectionFilter");50 qmlRegisterType<HistoryQmlIntersectionFilter>(uri, 0, 1, "HistoryIntersectionFilter");
4951
=== modified file 'Ubuntu/History/historythreadmodel.cpp'
--- Ubuntu/History/historythreadmodel.cpp 2014-08-07 19:22:31 +0000
+++ Ubuntu/History/historythreadmodel.cpp 2014-08-22 15:31:10 +0000
@@ -35,7 +35,8 @@
35Q_DECLARE_METATYPE(History::TextEventAttachments)35Q_DECLARE_METATYPE(History::TextEventAttachments)
3636
37HistoryThreadModel::HistoryThreadModel(QObject *parent) :37HistoryThreadModel::HistoryThreadModel(QObject *parent) :
38 QAbstractListModel(parent), mCanFetchMore(true), mFilter(0), mSort(0), mType(EventTypeText), mFetchTimer(0)38 QAbstractListModel(parent), mCanFetchMore(true), mFilter(0), mSort(0),
39 mType(EventTypeText), mUpdateTimer(0)
39{40{
40 // configure the roles41 // configure the roles
41 mRoles[AccountIdRole] = "accountId";42 mRoles[AccountIdRole] = "accountId";
@@ -66,7 +67,7 @@
66 connect(this, SIGNAL(modelReset()), SIGNAL(countChanged()));67 connect(this, SIGNAL(modelReset()), SIGNAL(countChanged()));
6768
68 // create the results view69 // create the results view
69 updateQuery();70 triggerQueryUpdate();
70}71}
7172
72int HistoryThreadModel::rowCount(const QModelIndex &parent) const73int HistoryThreadModel::rowCount(const QModelIndex &parent) const
@@ -213,7 +214,7 @@
213214
214void HistoryThreadModel::fetchMore(const QModelIndex &parent)215void HistoryThreadModel::fetchMore(const QModelIndex &parent)
215{216{
216 if (parent.isValid()) {217 if (parent.isValid() || mThreadView.isNull()) {
217 return;218 return;
218 }219 }
219220
@@ -249,11 +250,11 @@
249 if (mFilter) {250 if (mFilter) {
250 connect(mFilter,251 connect(mFilter,
251 SIGNAL(filterChanged()),252 SIGNAL(filterChanged()),
252 SLOT(updateQuery()));253 SLOT(triggerQueryUpdate()));
253 }254 }
254255
255 Q_EMIT filterChanged();256 Q_EMIT filterChanged();
256 updateQuery();257 triggerQueryUpdate();
257}258}
258259
259HistoryQmlSort *HistoryThreadModel::sort() const260HistoryQmlSort *HistoryThreadModel::sort() const
@@ -272,11 +273,11 @@
272 if (mSort) {273 if (mSort) {
273 connect(mSort,274 connect(mSort,
274 SIGNAL(sortChanged()),275 SIGNAL(sortChanged()),
275 SLOT(updateQuery()));276 SLOT(triggerQueryUpdate()));
276 }277 }
277278
278 Q_EMIT sortChanged();279 Q_EMIT sortChanged();
279 updateQuery();280 triggerQueryUpdate();
280}281}
281282
282HistoryThreadModel::EventType HistoryThreadModel::type() const283HistoryThreadModel::EventType HistoryThreadModel::type() const
@@ -288,7 +289,7 @@
288{289{
289 mType = value;290 mType = value;
290 Q_EMIT typeChanged();291 Q_EMIT typeChanged();
291 updateQuery();292 triggerQueryUpdate();
292}293}
293294
294QString HistoryThreadModel::threadIdForParticipants(const QString &accountId, int eventType, const QStringList &participants, int matchFlags, bool create)295QString HistoryThreadModel::threadIdForParticipants(const QString &accountId, int eventType, const QStringList &participants, int matchFlags, bool create)
@@ -324,6 +325,14 @@
324 return mThreads[row].properties();325 return mThreads[row].properties();
325}326}
326327
328void HistoryThreadModel::triggerQueryUpdate()
329{
330 if (mUpdateTimer) {
331 killTimer(mUpdateTimer);
332 }
333 mUpdateTimer = startTimer(100);
334}
335
327void HistoryThreadModel::updateQuery()336void HistoryThreadModel::updateQuery()
328{337{
329 // remove all events from the model338 // remove all events from the model
@@ -363,7 +372,7 @@
363 SLOT(onThreadsRemoved(History::Threads)));372 SLOT(onThreadsRemoved(History::Threads)));
364 connect(mThreadView.data(),373 connect(mThreadView.data(),
365 SIGNAL(invalidated()),374 SIGNAL(invalidated()),
366 SLOT(updateQuery()));375 SLOT(triggerQueryUpdate()));
367376
368 Q_FOREACH(const QVariant &attachment, mAttachmentCache) {377 Q_FOREACH(const QVariant &attachment, mAttachmentCache) {
369 HistoryQmlTextEventAttachment *qmlAttachment = attachment.value<HistoryQmlTextEventAttachment *>();378 HistoryQmlTextEventAttachment *qmlAttachment = attachment.value<HistoryQmlTextEventAttachment *>();
@@ -373,16 +382,10 @@
373 }382 }
374 mAttachmentCache.clear();383 mAttachmentCache.clear();
375384
376 if (mFetchTimer) {
377 killTimer(mFetchTimer);
378 }
379
380 // and fetch again385 // and fetch again
381 mCanFetchMore = true;386 mCanFetchMore = true;
382 Q_EMIT canFetchMoreChanged();387 Q_EMIT canFetchMoreChanged();
383388 fetchMore(QModelIndex());
384 // delay the loading just to give the settings some time to settle down
385 mFetchTimer = startTimer(100);
386}389}
387390
388void HistoryThreadModel::onThreadsAdded(const History::Threads &threads)391void HistoryThreadModel::onThreadsAdded(const History::Threads &threads)
@@ -430,10 +433,9 @@
430433
431void HistoryThreadModel::timerEvent(QTimerEvent *event)434void HistoryThreadModel::timerEvent(QTimerEvent *event)
432{435{
433 if (event->timerId() == mFetchTimer) {436 if (event->timerId() == mUpdateTimer) {
434 killTimer(mFetchTimer);437 killTimer(mUpdateTimer);
435 mFetchTimer = 0;438 mUpdateTimer = 0;
436439 updateQuery();
437 fetchMore(QModelIndex());
438 }440 }
439}441}
440442
=== modified file 'Ubuntu/History/historythreadmodel.h'
--- Ubuntu/History/historythreadmodel.h 2014-08-07 19:22:31 +0000
+++ Ubuntu/History/historythreadmodel.h 2014-08-22 15:31:10 +0000
@@ -125,6 +125,7 @@
125 void canFetchMoreChanged();125 void canFetchMoreChanged();
126126
127protected Q_SLOTS:127protected Q_SLOTS:
128 void triggerQueryUpdate();
128 void updateQuery();129 void updateQuery();
129 void onThreadsAdded(const History::Threads &threads);130 void onThreadsAdded(const History::Threads &threads);
130 void onThreadsModified(const History::Threads &threads);131 void onThreadsModified(const History::Threads &threads);
@@ -142,7 +143,7 @@
142 EventType mType;143 EventType mType;
143 QHash<int, QByteArray> mRoles;144 QHash<int, QByteArray> mRoles;
144 mutable QMap<History::TextEvent, QList<QVariant> > mAttachmentCache;145 mutable QMap<History::TextEvent, QList<QVariant> > mAttachmentCache;
145 int mFetchTimer;146 int mUpdateTimer;
146};147};
147148
148#endif // HISTORYTHREADMODEL_H149#endif // HISTORYTHREADMODEL_H
149150
=== modified file 'src/event.cpp'
--- src/event.cpp 2013-09-26 21:06:50 +0000
+++ src/event.cpp 2014-08-22 15:31:10 +0000
@@ -55,6 +55,7 @@
55 map[FieldEventId] = eventId;55 map[FieldEventId] = eventId;
56 map[FieldSenderId] = senderId;56 map[FieldSenderId] = senderId;
57 map[FieldTimestamp] = timestamp.toString(Qt::ISODate);57 map[FieldTimestamp] = timestamp.toString(Qt::ISODate);
58 map[FieldDate] = timestamp.date().toString(Qt::ISODate);
58 map[FieldNewEvent] = newEvent;59 map[FieldNewEvent] = newEvent;
59 map[FieldType] = type();60 map[FieldType] = type();
60 map[FieldParticipants] = participants;61 map[FieldParticipants] = participants;
@@ -243,6 +244,11 @@
243 return true;244 return true;
244}245}
245246
247bool Event::operator!=(const Event &other) const
248{
249 return !(*this == other);
250}
251
246bool Event::operator<(const Event &other) const252bool Event::operator<(const Event &other) const
247{253{
248 QString selfData = accountId() + threadId() + eventId();254 QString selfData = accountId() + threadId() + eventId();
249255
=== modified file 'src/event.h'
--- src/event.h 2013-09-26 21:06:50 +0000
+++ src/event.h 2014-08-22 15:31:10 +0000
@@ -56,6 +56,7 @@
56 QVariantMap properties() const;56 QVariantMap properties() const;
57 bool isNull() const;57 bool isNull() const;
58 bool operator==(const Event &other) const;58 bool operator==(const Event &other) const;
59 bool operator!=(const Event &other) const;
59 bool operator<(const Event &other) const;60 bool operator<(const Event &other) const;
6061
61protected:62protected:
6263
=== modified file 'src/types.h'
--- src/types.h 2014-06-25 11:45:09 +0000
+++ src/types.h 2014-08-22 15:31:10 +0000
@@ -106,6 +106,7 @@
106static const char* FieldUnreadCount = "unreadCount";106static const char* FieldUnreadCount = "unreadCount";
107static const char* FieldSenderId = "senderId";107static const char* FieldSenderId = "senderId";
108static const char* FieldTimestamp = "timestamp";108static const char* FieldTimestamp = "timestamp";
109static const char* FieldDate = "date";
109static const char* FieldNewEvent = "newEvent";110static const char* FieldNewEvent = "newEvent";
110111
111// text event fields112// text event fields

Subscribers

People subscribed via source and target branches