Merge lp:~zsombi/ubuntu-ui-toolkit/expose-alarm-id into lp:ubuntu-ui-toolkit/staging
- expose-alarm-id
- Merge into staging
Status: | Work in progress |
---|---|
Proposed branch: | lp:~zsombi/ubuntu-ui-toolkit/expose-alarm-id |
Merge into: | lp:ubuntu-ui-toolkit/staging |
Diff against target: |
639 lines (+268/-31) 14 files modified
components.api (+5/-3) src/Ubuntu/Components/plugin/adapters/alarmsadapter_organizer.cpp (+149/-18) src/Ubuntu/Components/plugin/adapters/alarmsadapter_p.h (+19/-0) src/Ubuntu/Components/plugin/alarmmanager_p.cpp (+5/-0) src/Ubuntu/Components/plugin/alarmmanager_p.h (+2/-0) src/Ubuntu/Components/plugin/alarmmanager_p_p.h (+1/-0) src/Ubuntu/Components/plugin/plugin.cpp (+2/-0) src/Ubuntu/Components/plugin/ucalarm.cpp (+12/-1) src/Ubuntu/Components/plugin/ucalarm.h (+3/-0) src/Ubuntu/Components/plugin/ucalarm_p.h (+2/-0) src/Ubuntu/Components/plugin/ucalarmmodel.cpp (+25/-9) src/Ubuntu/Components/plugin/ucalarmmodel.h (+4/-0) tests/resources/alarm/Alarms.qml (+2/-0) tests/unit/tst_alarms/tst_alarms.cpp (+37/-0) |
To merge this branch: | bzr merge lp:~zsombi/ubuntu-ui-toolkit/expose-alarm-id |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Cris Dywan | Needs Information | ||
PS Jenkins bot | continuous-integration | Needs Fixing | |
Nekhelesh Ramananthan | Pending | ||
Review via email:
|
Commit message
Exposing Alarm.identifier and AlarmModel.
Description of the change
Exposing Alarm.identifier and AlarmModel.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Cris Dywan (kalikiana) wrote : | # |
442 UCAlarm::~UCAlarm()
443 {
444 + if (!objectName(
445 + qDebug() << "DESTROYING" << objectName();
446 + }
Forgotten debug line? Or if this was intentional it should be a critical.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Zsombor Egri (zsombi) wrote : | # |
> 442 UCAlarm::~UCAlarm()
> 443 {
> 444 + if (!objectName(
> 445 + qDebug() << "DESTROYING" << objectName();
> 446 + }
>
> Forgotten debug line? Or if this was intentional it should be a critical.
Fixed. Thanks!
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1433
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1434
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1435
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
- 1436. By Zsombor Egri
-
staging sync
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1436
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Cris Dywan (kalikiana) wrote : | # |
What's up with this?
Unmerged revisions
- 1436. By Zsombor Egri
-
staging sync
- 1435. By Zsombor Egri
-
staging sync
- 1434. By Zsombor Egri
-
rogue debug removed
- 1433. By Zsombor Egri
-
staging merge
- 1432. By Zsombor Egri
-
alarms returned by get() and find() invokables are hashed to avoid OOM situation
- 1431. By Zsombor Egri
-
tests
- 1430. By Zsombor Egri
-
move JSON conversions into AlarmDataAdapter; data version handling added
- 1429. By Zsombor Egri
-
moving common code in separate functions
- 1428. By Zsombor Egri
-
store alarm ID as separate extended detail from activation URL; use private getter fro identifier, should be applied for the entire property set to simplify the code
- 1427. By Zsombor Egri
-
AlarmModel.find added
Preview Diff
1 | === modified file 'components.api' |
2 | --- components.api 2015-07-24 13:31:03 +0000 |
3 | +++ components.api 2015-07-27 08:49:11 +0000 |
4 | @@ -81,11 +81,12 @@ |
5 | Ubuntu.Components.ActivityIndicator 1.3: AnimatedItem |
6 | property bool onScreen |
7 | property bool running |
8 | -Ubuntu.Components.Alarm 1.0 0.1: QtObject |
9 | +Ubuntu.Components.Alarm 1.2 1.0 0.1: QtObject |
10 | property QDateTime date |
11 | property DaysOfWeek daysOfWeek |
12 | property bool enabled |
13 | readonly property int error |
14 | + readonly property string identifier 1.2 |
15 | property string message |
16 | function save() |
17 | function cancel() |
18 | @@ -134,10 +135,11 @@ |
19 | Fail |
20 | InProgress |
21 | Ready |
22 | -Ubuntu.Components.AlarmModel 1.0 0.1: QAbstractListModel |
23 | +Ubuntu.Components.AlarmModel 1.2 1.0 0.1: QAbstractListModel |
24 | readonly property int count |
25 | - function refresh() 1.0 |
26 | + function refresh() 1.2 |
27 | function UCAlarm* get(int index) |
28 | + function UCAlarm* find(string alarmId) 1.2 |
29 | Ubuntu.Components.Argument 1.0 0.1: QtObject |
30 | property string help |
31 | function var at(int i) |
32 | |
33 | === modified file 'src/Ubuntu/Components/plugin/adapters/alarmsadapter_organizer.cpp' |
34 | --- src/Ubuntu/Components/plugin/adapters/alarmsadapter_organizer.cpp 2015-03-24 16:51:39 +0000 |
35 | +++ src/Ubuntu/Components/plugin/adapters/alarmsadapter_organizer.cpp 2015-07-27 08:49:11 +0000 |
36 | @@ -29,6 +29,8 @@ |
37 | #include <QtCore/QJsonDocument> |
38 | #include <QtCore/QJsonObject> |
39 | #include <QtCore/QJsonArray> |
40 | +#include <QtCore/QUuid> |
41 | +#include <QtCore/QUrlQuery> |
42 | #include <QtCore/QDebug> |
43 | |
44 | #define ALARM_DATABASE "%1/alarms.json" |
45 | @@ -43,11 +45,46 @@ |
46 | #define ALARM_COLLECTION "Alarms" |
47 | |
48 | // special tags used as workaround for bug #1361702 |
49 | -const char *tagAlarmService = "x-canonical-alarm"; |
50 | -const char *tagDisabledAlarm = "x-canonical-disabled"; |
51 | +const char *tagAlarmService = "x-canonical-alarm"; |
52 | +const char *tagDisabledAlarm = "x-canonical-disabled"; |
53 | +const char *tagAlarmVersion = "x-canonical-alarm-version"; |
54 | +const char *tagAlarmId = "x-canonical-alarm-id"; |
55 | +const char *tagActivationUrl = "x-canonical-activation-url"; |
56 | + |
57 | +const char *currentAlarmsVersion= "1.1"; |
58 | |
59 | QTORGANIZER_USE_NAMESPACE |
60 | |
61 | +QString getEventDetail(const QOrganizerItem &item, const char *detailTag) |
62 | +{ |
63 | + QList<QOrganizerItemDetail> details = item.details(QOrganizerItemDetail::TypeExtendedDetail); |
64 | + for (int i = 0; i < details.count(); i++) { |
65 | + QOrganizerItemDetail detail = details[i]; |
66 | + if (detail.value(QOrganizerItemExtendedDetail::FieldName).toString() == QLatin1String(detailTag)) { |
67 | + return detail.value(QOrganizerItemExtendedDetail::FieldData).toString(); |
68 | + } |
69 | + } |
70 | + return QString(); |
71 | +} |
72 | + |
73 | +void setEventDetail(QOrganizerItem &item, const char *detailTag, const QString &data) |
74 | +{ |
75 | + // remove all previous identifiers from event |
76 | + QList<QOrganizerItemDetail> details = item.details(QOrganizerItemDetail::TypeExtendedDetail); |
77 | + for (int i = 0; i < details.count(); i++) { |
78 | + QOrganizerItemDetail detail = details[i]; |
79 | + if (detail.value(QOrganizerItemExtendedDetail::FieldName).toString() == QLatin1String(detailTag)) { |
80 | + item.removeDetail(&detail); |
81 | + break; |
82 | + } |
83 | + } |
84 | + // save the new detail |
85 | + QOrganizerItemExtendedDetail exData; |
86 | + exData.setName(detailTag); |
87 | + exData.setData(data); |
88 | + item.saveDetail(&exData); |
89 | +} |
90 | + |
91 | /*----------------------------------------------------------------------------- |
92 | * Adaptation layer for Alarm Data. |
93 | */ |
94 | @@ -171,6 +208,43 @@ |
95 | return true; |
96 | } |
97 | |
98 | +// retrieve the identifier |
99 | +QString AlarmDataAdapter::identifier() |
100 | +{ |
101 | + QString alarmId = getEventDetail(event, tagAlarmId); |
102 | + return alarmId; |
103 | +} |
104 | + |
105 | +// creates a new identifier and sets it to the event |
106 | +void AlarmDataAdapter::resetIdentifier(const QString &savedId) |
107 | +{ |
108 | + QString alarmId = savedId.isNull() ? QUuid::createUuid().toString() : savedId; |
109 | + setEventDetail(event, tagAlarmId, alarmId); |
110 | + changes |= AlarmManager::Identifier; |
111 | + |
112 | + // update activation url as well |
113 | + QUrl url("alarm://open"); |
114 | + QUrlQuery query; |
115 | + query.addQueryItem("alarmId", alarmId); |
116 | + url.setQuery(query); |
117 | + setEventDetail(event, tagActivationUrl, url.toString()); |
118 | +} |
119 | + |
120 | +// upgrade alarm data to the current version; returns true if upgare was needed |
121 | +bool AlarmDataAdapter::upgradeAlarmData() |
122 | +{ |
123 | + QString version = getEventDetail(event, tagAlarmVersion); |
124 | + if (version.isEmpty() || version == QStringLiteral("1.0")) { |
125 | + // version 1.0, upgrade |
126 | + resetIdentifier(); |
127 | + // finally upgare to the current version |
128 | + setEventDetail(event, tagAlarmVersion, currentAlarmsVersion); |
129 | + return true; |
130 | + } |
131 | + return false; |
132 | +} |
133 | + |
134 | + |
135 | QVariant AlarmDataAdapter::cookie() const |
136 | { |
137 | return QVariant::fromValue(event.id()); |
138 | @@ -214,6 +288,12 @@ |
139 | if (event.id().managerUri().isEmpty()) { |
140 | changes = AlarmManager::AllFields; |
141 | } |
142 | + |
143 | + // make sure the alarm has an identifier set |
144 | + if (identifier().isEmpty()) { |
145 | + resetIdentifier(); |
146 | + } |
147 | + |
148 | QOrganizerItemSaveRequest *saveRequest = new QOrganizerItemSaveRequest(q_ptr); |
149 | saveRequest->setItem(event); |
150 | request = saveRequest; |
151 | @@ -375,6 +455,37 @@ |
152 | } |
153 | } |
154 | |
155 | +void AlarmDataAdapter::eventFromJson(const QJsonObject &object) |
156 | +{ |
157 | + q_ptr->setMessage(object["message"].toString()); |
158 | + q_ptr->setDate(QDateTime::fromString(object["date"].toString())); |
159 | + q_ptr->setSound(object["sound"].toString()); |
160 | + q_ptr->setType(static_cast<UCAlarm::AlarmType>(object["type"].toInt())); |
161 | + q_ptr->setDaysOfWeek(static_cast<UCAlarm::DaysOfWeek>(object["days"].toInt())); |
162 | + q_ptr->setEnabled(object["enabled"].toBool()); |
163 | + setEventDetail(event, tagAlarmId, object[tagAlarmId].toString()); |
164 | + setEventDetail(event, tagActivationUrl, object[tagActivationUrl].toString()); |
165 | + setEventDetail(event, tagAlarmVersion, object[tagAlarmVersion].toString()); |
166 | + // call checkAlarm to complete field checks (i.e. type vs daysOfWeek, kick date, etc) |
167 | + checkAlarm(); |
168 | +} |
169 | + |
170 | +QJsonObject AlarmDataAdapter::eventToJson() |
171 | +{ |
172 | + QJsonObject object; |
173 | + object[tagAlarmVersion] = QJsonValue(currentAlarmsVersion); |
174 | + object["message"] = message(); |
175 | + object["date"] = date().toString(); |
176 | + object["sound"] = sound().toString(); |
177 | + object["type"] = QJsonValue(type()); |
178 | + object["days"] = QJsonValue(daysOfWeek()); |
179 | + object["enabled"] = QJsonValue(enabled()); |
180 | + object[tagAlarmId] = QJsonValue(identifier()); |
181 | + object[tagActivationUrl] = QJsonValue(getEventDetail(event, tagActivationUrl)); |
182 | + return object; |
183 | +} |
184 | + |
185 | + |
186 | /*----------------------------------------------------------------------------- |
187 | * Adaptation layer for Alarms. |
188 | */ |
189 | @@ -475,6 +586,9 @@ |
190 | if (!file.open(QFile::ReadOnly)) { |
191 | return; |
192 | } |
193 | + // block the manager signals till we load the alarm data into memory |
194 | + manager->blockSignals(true); |
195 | + |
196 | QByteArray data = file.readAll(); |
197 | QJsonDocument document(QJsonDocument::fromJson(data)); |
198 | QJsonArray array = document.array(); |
199 | @@ -483,20 +597,14 @@ |
200 | |
201 | // use UCAlarm to save store JSON data |
202 | UCAlarm alarm; |
203 | - alarm.setMessage(object["message"].toString()); |
204 | - alarm.setDate(QDateTime::fromString(object["date"].toString())); |
205 | - alarm.setSound(object["sound"].toString()); |
206 | - alarm.setType(static_cast<UCAlarm::AlarmType>(object["type"].toInt())); |
207 | - alarm.setDaysOfWeek(static_cast<UCAlarm::DaysOfWeek>(object["days"].toInt())); |
208 | - alarm.setEnabled(object["enabled"].toBool()); |
209 | - |
210 | AlarmDataAdapter *pAlarm = static_cast<AlarmDataAdapter*>(UCAlarmPrivate::get(&alarm)); |
211 | - // call checkAlarm to complete field checks (i.e. type vs daysOfWeek, kick date, etc) |
212 | - pAlarm->checkAlarm(); |
213 | + pAlarm->eventFromJson(object); |
214 | QOrganizerTodo event = pAlarm->data(); |
215 | manager->saveItem(&event); |
216 | } |
217 | file.close(); |
218 | + // unblock signals |
219 | + manager->blockSignals(false); |
220 | } |
221 | |
222 | // save fallback manager data only |
223 | @@ -517,13 +625,8 @@ |
224 | for(int i = 0; i < alarmList.count(); i++) { |
225 | // create an UCAlarm and set its event to ease conversions |
226 | const UCAlarm *alarm = alarmList[i]; |
227 | - QJsonObject object; |
228 | - object["message"] = alarm->message(); |
229 | - object["date"] = alarm->date().toString(); |
230 | - object["sound"] = alarm->sound().toString(); |
231 | - object["type"] = QJsonValue(alarm->type()); |
232 | - object["days"] = QJsonValue(alarm->daysOfWeek()); |
233 | - object["enabled"] = QJsonValue(alarm->enabled()); |
234 | + AlarmDataAdapter *pAlarm = static_cast<AlarmDataAdapter*>(UCAlarmPrivate::get(alarm)); |
235 | + QJsonObject object = pAlarm->eventToJson(); |
236 | data.append(object); |
237 | |
238 | } |
239 | @@ -662,6 +765,12 @@ |
240 | return false; |
241 | } |
242 | |
243 | +UCAlarm *AlarmsAdapter::findAlarm(const QString &alarmId) const |
244 | +{ |
245 | + Q_ASSERT(!alarmId.isEmpty()); |
246 | + return const_cast<UCAlarm*>(alarmList.find(alarmId)); |
247 | +} |
248 | + |
249 | // returns a todo event from an ID, which can be an occurence |
250 | QOrganizerTodo AlarmsAdapter::todoItem(const QOrganizerItemId &id) |
251 | { |
252 | @@ -756,6 +865,12 @@ |
253 | |
254 | QSet<QOrganizerItemId> parentId; |
255 | QOrganizerTodo event; |
256 | + bool upgraded = false; |
257 | + |
258 | + // disable manager signals till we fetch the alarms so in case we must upgrade |
259 | + // an alarm we won't get update signals |
260 | + manager->blockSignals(true); |
261 | + |
262 | Q_FOREACH(const QOrganizerItem &item, fetchRequest->items()) { |
263 | // repeating alarms may be fetched as occurences, therefore check their parent event |
264 | if (item.type() == QOrganizerItemType::TypeTodoOccurrence) { |
265 | @@ -776,10 +891,26 @@ |
266 | UCAlarm alarm; |
267 | AlarmDataAdapter *pAlarm = static_cast<AlarmDataAdapter*>(UCAlarmPrivate::get(&alarm)); |
268 | pAlarm->setData(event); |
269 | + // check if we need to upgrade the event to the current version |
270 | + if (pAlarm->upgradeAlarmData()) { |
271 | + // use synchronous save so we omit async signal replies |
272 | + event = pAlarm->data(); |
273 | + manager->saveItem(&event); |
274 | + saveAlarms(); |
275 | + upgraded = true; |
276 | + } |
277 | adjustAlarmOccurrence(*pAlarm); |
278 | alarmList.insert(alarm); |
279 | } |
280 | |
281 | + // save upgrades |
282 | + if (upgraded) { |
283 | + saveAlarms(); |
284 | + } |
285 | + |
286 | + // re-enable manager signals |
287 | + manager->blockSignals(false); |
288 | + |
289 | completed = true; |
290 | Q_EMIT q_ptr->alarmsRefreshed(); |
291 | } |
292 | |
293 | === modified file 'src/Ubuntu/Components/plugin/adapters/alarmsadapter_p.h' |
294 | --- src/Ubuntu/Components/plugin/adapters/alarmsadapter_p.h 2015-03-24 16:51:39 +0000 |
295 | +++ src/Ubuntu/Components/plugin/adapters/alarmsadapter_p.h 2015-07-27 08:49:11 +0000 |
296 | @@ -49,6 +49,8 @@ |
297 | bool setDaysOfWeek(UCAlarm::DaysOfWeek days); |
298 | QUrl sound() const; |
299 | bool setSound(const QUrl &sound); |
300 | + QString identifier(); |
301 | + void resetIdentifier(const QString &savedId = QString()); |
302 | QVariant cookie() const; |
303 | UCAlarm::Error checkAlarm(); |
304 | |
305 | @@ -62,6 +64,7 @@ |
306 | |
307 | // adaptation specific data |
308 | void adjustDowSettings(UCAlarm::AlarmType type, UCAlarm::DaysOfWeek days); |
309 | + bool upgradeAlarmData(); |
310 | static QSet<Qt::DayOfWeek> daysToSet(int days); |
311 | static UCAlarm::DaysOfWeek daysFromSet(const QSet<Qt::DayOfWeek> &set); |
312 | |
313 | @@ -71,6 +74,9 @@ |
314 | } |
315 | void setData(const QOrganizerTodo &data); |
316 | |
317 | + void eventFromJson(const QJsonObject &object); |
318 | + QJsonObject eventToJson(); |
319 | + |
320 | protected: |
321 | QOrganizerTodo event; |
322 | UCAlarm::AlarmType alarmType; |
323 | @@ -140,6 +146,18 @@ |
324 | UCAlarm *alarm = takeAt(index); |
325 | delete alarm; |
326 | } |
327 | + // find an alarm from its ID |
328 | + const UCAlarm *find(const QString &alarmId) const |
329 | + { |
330 | + QMapIterator< QPair<QDateTime, QOrganizerItemId>, UCAlarm* > i(data); |
331 | + while (i.hasNext()) { |
332 | + i.next(); |
333 | + if (UCAlarmPrivate::get(i.value())->identifier() == alarmId) { |
334 | + return i.value(); |
335 | + } |
336 | + } |
337 | + return NULL; |
338 | + } |
339 | |
340 | protected: |
341 | // removes alarm data at index and returns the alarm pointer |
342 | @@ -183,6 +201,7 @@ |
343 | int alarmCount(); |
344 | UCAlarm *getAlarmAt(int index) const; |
345 | bool findAlarm(const UCAlarm &alarm, const QVariant &cookie) const; |
346 | + UCAlarm *findAlarm(const QString &alarmId) const; |
347 | void adjustAlarmOccurrence(AlarmDataAdapter &alarm); |
348 | |
349 | void loadAlarms(); |
350 | |
351 | === modified file 'src/Ubuntu/Components/plugin/alarmmanager_p.cpp' |
352 | --- src/Ubuntu/Components/plugin/alarmmanager_p.cpp 2015-02-26 15:09:23 +0000 |
353 | +++ src/Ubuntu/Components/plugin/alarmmanager_p.cpp 2015-07-27 08:49:11 +0000 |
354 | @@ -78,6 +78,11 @@ |
355 | return &alarm; |
356 | } |
357 | |
358 | +UCAlarm *AlarmManager::findAlarm(const QString &alarmId) const |
359 | +{ |
360 | + return d_ptr->findAlarm(alarmId); |
361 | +} |
362 | + |
363 | bool AlarmManager::verifyChange(UCAlarm *alarm, Change change, const QVariant &newData) |
364 | { |
365 | return d_ptr->verifyChange(alarm, change, newData); |
366 | |
367 | === modified file 'src/Ubuntu/Components/plugin/alarmmanager_p.h' |
368 | --- src/Ubuntu/Components/plugin/alarmmanager_p.h 2015-02-26 10:27:56 +0000 |
369 | +++ src/Ubuntu/Components/plugin/alarmmanager_p.h 2015-07-27 08:49:11 +0000 |
370 | @@ -89,6 +89,7 @@ |
371 | Sound = 0x0008, |
372 | Type = 0x0010, |
373 | Days = 0x0020, |
374 | + Identifier = 0x0040, |
375 | AllFields = 0x00FF |
376 | }; |
377 | |
378 | @@ -100,6 +101,7 @@ |
379 | int alarmCount(); |
380 | UCAlarm *alarmAt(int index); |
381 | UCAlarm *findAlarm(const QVariant &cookie) const; |
382 | + UCAlarm *findAlarm(const QString &alarmId) const; |
383 | |
384 | bool verifyChange(UCAlarm *alarm, Change change, const QVariant &newData); |
385 | static UCAlarmPrivate *createAlarmData(UCAlarm *alarm); |
386 | |
387 | === modified file 'src/Ubuntu/Components/plugin/alarmmanager_p_p.h' |
388 | --- src/Ubuntu/Components/plugin/alarmmanager_p_p.h 2015-02-26 15:09:23 +0000 |
389 | +++ src/Ubuntu/Components/plugin/alarmmanager_p_p.h 2015-07-27 08:49:11 +0000 |
390 | @@ -47,6 +47,7 @@ |
391 | virtual int alarmCount() = 0; |
392 | virtual UCAlarm *getAlarmAt(int index) const = 0; |
393 | virtual bool findAlarm(const UCAlarm &alarm, const QVariant &cookie) const = 0; |
394 | + virtual UCAlarm *findAlarm(const QString &alarmId) const = 0; |
395 | |
396 | // function to verify whether the given alarm property has a given value set |
397 | // used for testing purposes |
398 | |
399 | === modified file 'src/Ubuntu/Components/plugin/plugin.cpp' |
400 | --- src/Ubuntu/Components/plugin/plugin.cpp 2015-07-19 17:44:46 +0000 |
401 | +++ src/Ubuntu/Components/plugin/plugin.cpp 2015-07-27 08:49:11 +0000 |
402 | @@ -197,6 +197,8 @@ |
403 | qmlRegisterType<UCServiceProperties, 1>(uri, 1, 1, "ServiceProperties"); |
404 | |
405 | // register 1.2 only API |
406 | + qmlRegisterType<UCAlarm, 1>(uri, 1, 2, "Alarm"); |
407 | + qmlRegisterType<UCAlarmModel, 1>(uri, 1, 2, "AlarmModel"); |
408 | qmlRegisterType<UCListItem>(uri, 1, 2, "ListItem"); |
409 | qmlRegisterType<UCListItemDivider>(); |
410 | qmlRegisterUncreatableType<UCSwipeEvent>(uri, 1, 2, "SwipeEvent", "This is an event object."); |
411 | |
412 | === modified file 'src/Ubuntu/Components/plugin/ucalarm.cpp' |
413 | --- src/Ubuntu/Components/plugin/ucalarm.cpp 2015-03-03 13:47:48 +0000 |
414 | +++ src/Ubuntu/Components/plugin/ucalarm.cpp 2015-07-27 08:49:11 +0000 |
415 | @@ -41,6 +41,7 @@ |
416 | setMessage(UbuntuI18n::instance().tr("Alarm")); |
417 | setType(UCAlarm::OneTime); |
418 | setDaysOfWeek(UCAlarm::AutoDetect); |
419 | + resetIdentifier(); |
420 | } |
421 | |
422 | void UCAlarmPrivate::_q_syncStatus(int operation, int status, int error) { |
423 | @@ -64,6 +65,8 @@ |
424 | Q_EMIT q->typeChanged(); |
425 | if (changes & AlarmManager::Days) |
426 | Q_EMIT q->daysOfWeekChanged(); |
427 | + if (changes & AlarmManager::Identifier) |
428 | + Q_EMIT q->identifierChanged(); |
429 | changes = 0; |
430 | } |
431 | |
432 | @@ -482,7 +485,7 @@ |
433 | * The property holds the alarm's sound to be played when the alarm is triggered. |
434 | * An empty url will mean to play the default sound. |
435 | * |
436 | - * The defaul tvalue is an empty url. |
437 | + * The default value is an empty url. |
438 | */ |
439 | QUrl UCAlarm::sound() const |
440 | { |
441 | @@ -497,6 +500,14 @@ |
442 | } |
443 | |
444 | /*! |
445 | + * \qmlproperty string Alarm::identifier |
446 | + * \readonly |
447 | + * \since Ubuntu.Components 1.2 |
448 | + * The property specifies the unique identifier of the alarm. The identifier is |
449 | + * set when created or when \l reset. |
450 | + */ |
451 | + |
452 | +/*! |
453 | * \qmlproperty Error Alarm::error |
454 | * The property holds the error code occurred during the last performed operation. |
455 | * |
456 | |
457 | === modified file 'src/Ubuntu/Components/plugin/ucalarm.h' |
458 | --- src/Ubuntu/Components/plugin/ucalarm.h 2014-10-09 13:02:27 +0000 |
459 | +++ src/Ubuntu/Components/plugin/ucalarm.h 2015-07-27 08:49:11 +0000 |
460 | @@ -37,6 +37,7 @@ |
461 | |
462 | Q_PROPERTY(int error READ error NOTIFY errorChanged) |
463 | Q_PROPERTY(Status status READ status NOTIFY statusChanged) |
464 | + Q_PRIVATE_PROPERTY(d_ptr, QString identifier READ identifier NOTIFY identifierChanged REVISION 1) |
465 | |
466 | Q_ENUMS(Status Operation Error AlarmType DayOfWeek) |
467 | Q_FLAGS(DaysOfWeek) |
468 | @@ -121,6 +122,8 @@ |
469 | void errorChanged(); |
470 | void statusChanged(Operation operation); |
471 | |
472 | + Q_REVISION(1) void identifierChanged(); |
473 | + |
474 | public Q_SLOTS: |
475 | void save(); |
476 | void cancel(); |
477 | |
478 | === modified file 'src/Ubuntu/Components/plugin/ucalarm_p.h' |
479 | --- src/Ubuntu/Components/plugin/ucalarm_p.h 2015-03-24 16:51:39 +0000 |
480 | +++ src/Ubuntu/Components/plugin/ucalarm_p.h 2015-07-27 08:49:11 +0000 |
481 | @@ -51,6 +51,8 @@ |
482 | virtual bool setDaysOfWeek(UCAlarm::DaysOfWeek days) = 0; |
483 | virtual QUrl sound() const = 0; |
484 | virtual bool setSound(const QUrl &sound) = 0; |
485 | + virtual QString identifier() = 0; |
486 | + virtual void resetIdentifier(const QString &savedId = QString()) = 0; |
487 | virtual QVariant cookie() const = 0; |
488 | virtual UCAlarm::Error checkAlarm() = 0; |
489 | |
490 | |
491 | === modified file 'src/Ubuntu/Components/plugin/ucalarmmodel.cpp' |
492 | --- src/Ubuntu/Components/plugin/ucalarmmodel.cpp 2015-06-16 13:15:41 +0000 |
493 | +++ src/Ubuntu/Components/plugin/ucalarmmodel.cpp 2015-07-27 08:49:11 +0000 |
494 | @@ -22,7 +22,6 @@ |
495 | #include "alarmmanager_p.h" |
496 | #include <QtQml/QQmlPropertyMap> |
497 | #include <QtQml/QQmlInfo> |
498 | -#include <QtQml/QQmlEngine> |
499 | |
500 | /*! |
501 | * \qmltype AlarmModel |
502 | @@ -156,6 +155,19 @@ |
503 | refresh(); |
504 | } |
505 | |
506 | +UCAlarm *UCAlarmModel::hashedAlarm(UCAlarm *alarm) |
507 | +{ |
508 | + UCAlarm *result = 0; |
509 | + const QString &id = UCAlarmPrivate::get(alarm)->identifier(); |
510 | + result = alarmHash.value(id).data(); |
511 | + if (!result) { |
512 | + result = new UCAlarm(this); |
513 | + UCAlarmPrivate::get(result)->copyAlarmData(*alarm); |
514 | + alarmHash.insert(id, QPointer<UCAlarm>(result)); |
515 | + } |
516 | + return result; |
517 | +} |
518 | + |
519 | int UCAlarmModel::rowCount(const QModelIndex &parent) const |
520 | { |
521 | Q_UNUSED(parent); |
522 | @@ -215,14 +227,18 @@ |
523 | */ |
524 | UCAlarm* UCAlarmModel::get(int index) |
525 | { |
526 | - UCAlarm *alarm = AlarmManager::instance().alarmAt(index); |
527 | - if (alarm) { |
528 | - UCAlarm *tempAlarm = new UCAlarm(this); |
529 | - UCAlarmPrivate::get(tempAlarm)->copyAlarmData(*alarm); |
530 | - alarm = tempAlarm; |
531 | - QQmlEngine::setObjectOwnership(tempAlarm, QQmlEngine::JavaScriptOwnership); |
532 | - } |
533 | - return alarm; |
534 | + return hashedAlarm(AlarmManager::instance().alarmAt(index)); |
535 | +} |
536 | + |
537 | +/*! |
538 | + * \qmlmethod Alarm AlarmModel::find(string alarmId) |
539 | + * \since Ubuntu.Components 1.2 |
540 | + * The function returns the alarm identified by the \c alarmId. The \c alarmId |
541 | + * cannot be an empty string. Returns null on error. |
542 | + */ |
543 | +UCAlarm *UCAlarmModel::find(const QString &alarmId) |
544 | +{ |
545 | + return hashedAlarm(AlarmManager::instance().findAlarm(alarmId)); |
546 | } |
547 | |
548 | /*! |
549 | |
550 | === modified file 'src/Ubuntu/Components/plugin/ucalarmmodel.h' |
551 | --- src/Ubuntu/Components/plugin/ucalarmmodel.h 2015-06-16 11:34:02 +0000 |
552 | +++ src/Ubuntu/Components/plugin/ucalarmmodel.h 2015-07-27 08:49:11 +0000 |
553 | @@ -43,6 +43,7 @@ |
554 | |
555 | // invokables |
556 | Q_INVOKABLE UCAlarm *get(int index); |
557 | + Q_REVISION(1) Q_INVOKABLE UCAlarm *find(const QString &alarmId); |
558 | |
559 | // property getters |
560 | int count() const; |
561 | @@ -65,7 +66,10 @@ |
562 | void moveFinished(); |
563 | |
564 | private: |
565 | + QHash<QString, QPointer<UCAlarm> > alarmHash; |
566 | bool m_moved:1; |
567 | + |
568 | + UCAlarm *hashedAlarm(UCAlarm *alarm); |
569 | }; |
570 | |
571 | #endif // UCALARMSMODEL_H |
572 | |
573 | === modified file 'tests/resources/alarm/Alarms.qml' |
574 | --- tests/resources/alarm/Alarms.qml 2015-03-03 13:20:06 +0000 |
575 | +++ tests/resources/alarm/Alarms.qml 2015-07-27 08:49:11 +0000 |
576 | @@ -26,6 +26,8 @@ |
577 | height: units.gu(71) |
578 | objectName: "mainView" |
579 | |
580 | + applicationName: "com.canonical.alarmtest" |
581 | + |
582 | AlarmModel{ |
583 | id: alarmModel |
584 | } |
585 | |
586 | === modified file 'tests/unit/tst_alarms/tst_alarms.cpp' |
587 | --- tests/unit/tst_alarms/tst_alarms.cpp 2014-11-20 06:36:45 +0000 |
588 | +++ tests/unit/tst_alarms/tst_alarms.cpp 2015-07-27 08:49:11 +0000 |
589 | @@ -103,6 +103,15 @@ |
590 | return false; |
591 | } |
592 | |
593 | + QString createOneTime(const QString &message) |
594 | + { |
595 | + UCAlarm alarm(QDateTime::currentDateTime(), UCAlarm::AutoDetect, "test_" + message); |
596 | + alarm.setSound(QUrl("file:///usr/share/sounds/ubuntu/ringtones/Bliss.ogg")); |
597 | + alarm.save(); |
598 | + waitForInsert(); |
599 | + return UCAlarmPrivate::get(&alarm)->identifier(); |
600 | + } |
601 | + |
602 | private Q_SLOTS: |
603 | |
604 | void initTestCase() |
605 | @@ -583,6 +592,34 @@ |
606 | // check the tags |
607 | QVERIFY(AlarmManager::instance().verifyChange(&alarm, AlarmManager::Enabled, enabled)); |
608 | } |
609 | + |
610 | + void test_alarm_identifier() |
611 | + { |
612 | + UCAlarm alarm; |
613 | + QVERIFY(!UCAlarmPrivate::get(&alarm)->identifier().isEmpty()); |
614 | + } |
615 | + |
616 | + void test_alarm_identifier_differs_on_reset() |
617 | + { |
618 | + UCAlarm alarm; |
619 | + QString id = UCAlarmPrivate::get(&alarm)->identifier(); |
620 | + alarm.reset(); |
621 | + QVERIFY(!UCAlarmPrivate::get(&alarm)->identifier().isEmpty()); |
622 | + QVERIFY(UCAlarmPrivate::get(&alarm)->identifier() != id); |
623 | + } |
624 | + |
625 | + void test_find_alarm_by_id() |
626 | + { |
627 | + QStringList ids; |
628 | + for (int i = 0; i < 5; i++) { |
629 | + ids << createOneTime(QString("find_alarm_by_id_%1").arg(i)); |
630 | + } |
631 | + |
632 | + UCAlarmModel model; |
633 | + for (int i = 0; i < ids.count(); i++) { |
634 | + QVERIFY(model.find(ids[i])); |
635 | + } |
636 | + } |
637 | }; |
638 | |
639 | QTEST_MAIN(tst_UCAlarms) |
PASSED: Continuous integration, rev:1431 jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- ci/1604/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 2005 jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- vivid-amd64- ci/331 jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- vivid-armhf- ci/334 jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- vivid-armhf- ci/334/ artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- vivid-i386- ci/331 jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- runner- vivid-mako/ 1766 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 2003 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 2003/artifact/ work/output/ *zip*/output. zip s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 19225
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/ubuntu- sdk-team- ubuntu- ui-toolkit- staging- ci/1604/ rebuild
http://