Merge lp:~artmello/messaging-app/messaging-app-video_attachment into lp:messaging-app
- messaging-app-video_attachment
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 488 |
Proposed branch: | lp:~artmello/messaging-app/messaging-app-video_attachment |
Merge into: | lp:messaging-app |
Prerequisite: | lp:~boiko/messaging-app/more_attachment_types |
Diff against target: |
1483 lines (+1035/-123) 20 files modified
debian/control (+2/-0) src/CMakeLists.txt (+2/-0) src/fileoperations.cpp (+48/-0) src/fileoperations.h (+39/-0) src/messagingapplication.cpp (+28/-1) src/messagingapplication.h (+7/-1) src/qml/AttachmentPanel.qml (+2/-3) src/qml/ComposeBar.qml (+2/-0) src/qml/MMS/MMSImage.qml (+1/-0) src/qml/MMS/MMSVideo.qml (+60/-44) src/qml/MMS/PreviewerImage.qml (+183/-8) src/qml/MMS/PreviewerVideo.qml (+124/-33) src/qml/MMSDelegate.qml (+6/-7) src/qml/ThumbnailVideo.qml (+76/-0) src/qml/messaging-app.qml (+3/-1) tests/qml/CMakeLists.txt (+34/-25) tests/qml/tst_MMSDelegate.qml (+167/-0) tests/qml/tst_PreviewerImage.qml (+103/-0) tests/qml/tst_PreviewerVideo.qml (+87/-0) tests/qml/tst_QmlTests.cpp (+61/-0) |
To merge this branch: | bzr merge lp:~artmello/messaging-app/messaging-app-video_attachment |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Tiago Salem Herrmann (community) | Needs Fixing | ||
Review via email: mp+278476@code.launchpad.net |
Commit message
Add video attachment delegates
Description of the change
Add video attachment delegates
- 476. By Arthur Mello
-
Update headers
PS Jenkins bot (ps-jenkins) wrote : | # |
- 477. By Arthur Mello
-
Add initial qml test
- 478. By Arthur Mello
-
Change on MMSDelegate to look for participants from messageData
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:477
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:478
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Tiago Salem Herrmann (tiagosh) : | # |
- 479. By Arthur Mello
-
Add QML tests for MMSDelegate
- 480. By Arthur Mello
-
Add PreviewerImage QML tests
- 481. By Arthur Mello
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:481
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 482. By Arthur Mello
-
Add TODO message for FileOperations
Remove mimetype check used for testing
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:482
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 483. By Arthur Mello
-
Change QML test structure so we could include messaingapp.private
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:483
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 484. By Arthur Mello
-
Fix build
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:484
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 485. By Arthur Mello
-
Add PreviewerVideo qml tests
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:485
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 486. By Arthur Mello
-
Merge with parent
- 487. By Arthur Mello
-
Add build dep
- 488. By Arthur Mello
-
Add build dep
- 489. By Arthur Mello
-
Fix QML test
- 490. By Arthur Mello
-
Fix QML tests
- 491. By Arthur Mello
-
Add sample file
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:486
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:491
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 492. By Arthur Mello
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:492
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 493. By Arthur Mello
-
Add Video Thumbnail
- 494. By Arthur Mello
-
Fix typo
- 495. By Arthur Mello
-
Show ActivityIndicator while loading thumbnail
Fix thumbnail path
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:493
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:495
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 496. By Arthur Mello
-
Use VideoOutput instead of Video QML component
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:496
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 497. By Arthur Mello
-
Merge with parent branch
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:497
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 498. By Arthur Mello
-
Merge with parent branch
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:498
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'debian/control' |
2 | --- debian/control 2015-09-11 14:25:57 +0000 |
3 | +++ debian/control 2015-12-08 18:33:04 +0000 |
4 | @@ -21,8 +21,10 @@ |
5 | qtdeclarative5-ubuntu-telephony0.1 | qtdeclarative5-ubuntu-telephony-plugin, |
6 | qtdeclarative5-ubuntu-content1, |
7 | qtdeclarative5-ubuntu-addressbook0.1, |
8 | + qtdeclarative5-ubuntu-thumbnailer0.1, |
9 | qtdeclarative5-qtcontacts-plugin, |
10 | qml-module-qt-labs-settings, |
11 | + qml-module-qtmultimedia, |
12 | qtpim5-dev, |
13 | xvfb, |
14 | Standards-Version: 3.9.4 |
15 | |
16 | === modified file 'src/CMakeLists.txt' |
17 | --- src/CMakeLists.txt 2015-02-24 13:33:31 +0000 |
18 | +++ src/CMakeLists.txt 2015-12-08 18:33:04 +0000 |
19 | @@ -1,10 +1,12 @@ |
20 | set(MESSAGING_APP messaging-app) |
21 | |
22 | set(messaging_app_HDRS |
23 | + fileoperations.h |
24 | messagingapplication.h |
25 | ) |
26 | |
27 | set(messaging_app_SRCS |
28 | + fileoperations.cpp |
29 | messagingapplication.cpp |
30 | main.cpp |
31 | ) |
32 | |
33 | === added file 'src/fileoperations.cpp' |
34 | --- src/fileoperations.cpp 1970-01-01 00:00:00 +0000 |
35 | +++ src/fileoperations.cpp 2015-12-08 18:33:04 +0000 |
36 | @@ -0,0 +1,48 @@ |
37 | +/* |
38 | + * Copyright (C) 2015 Canonical, Ltd. |
39 | + * |
40 | + * Authors: |
41 | + * Arthur Mello <arthur.mello@canonical.com> |
42 | + * |
43 | + * This file is part of messaging-app. |
44 | + * |
45 | + * messaging-app is free software; you can redistribute it and/or modify |
46 | + * it under the terms of the GNU General Public License as published by |
47 | + * the Free Software Foundation; version 3. |
48 | + * |
49 | + * messaging-app is distributed in the hope that it will be useful, |
50 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
51 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
52 | + * GNU General Public License for more details. |
53 | + * |
54 | + * You should have received a copy of the GNU General Public License |
55 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
56 | + */ |
57 | + |
58 | +#include "fileoperations.h" |
59 | + |
60 | +#include <QDir> |
61 | +#include <QFile> |
62 | +#include <QTemporaryFile> |
63 | + |
64 | +FileOperations::FileOperations(QObject *parent) |
65 | + : QObject(parent) |
66 | +{ |
67 | +} |
68 | + |
69 | +FileOperations::~FileOperations() |
70 | +{ |
71 | +} |
72 | + |
73 | +QString FileOperations::getTemporaryFile(const QString &fileExtension) const |
74 | +{ |
75 | + //TODO remove once lp:1420728 is fixed |
76 | + QTemporaryFile tmp(QDir::tempPath() + "/tmpXXXXXX" + fileExtension); |
77 | + tmp.open(); |
78 | + return tmp.fileName(); |
79 | +} |
80 | + |
81 | +bool FileOperations::link(const QString &from, const QString &to) |
82 | +{ |
83 | + return QFile::link(from, to); |
84 | +} |
85 | |
86 | === added file 'src/fileoperations.h' |
87 | --- src/fileoperations.h 1970-01-01 00:00:00 +0000 |
88 | +++ src/fileoperations.h 2015-12-08 18:33:04 +0000 |
89 | @@ -0,0 +1,39 @@ |
90 | +/* |
91 | + * Copyright (C) 2015 Canonical, Ltd. |
92 | + * |
93 | + * Authors: |
94 | + * Arthur Mello <arthur.mello@canonical.com> |
95 | + * |
96 | + * This file is part of messaging-app. |
97 | + * |
98 | + * messaging-app is free software; you can redistribute it and/or modify |
99 | + * it under the terms of the GNU General Public License as published by |
100 | + * the Free Software Foundation; version 3. |
101 | + * |
102 | + * messaging-app is distributed in the hope that it will be useful, |
103 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
104 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
105 | + * GNU General Public License for more details. |
106 | + * |
107 | + * You should have received a copy of the GNU General Public License |
108 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
109 | + */ |
110 | + |
111 | +#ifndef FILEOPERATIONS_H |
112 | +#define FILEOPERATIONS_H |
113 | + |
114 | +#include <QObject> |
115 | + |
116 | +class FileOperations : public QObject |
117 | +{ |
118 | + Q_OBJECT |
119 | + |
120 | +public: |
121 | + FileOperations(QObject *parent = 0); |
122 | + ~FileOperations(); |
123 | + |
124 | + Q_INVOKABLE QString getTemporaryFile(const QString &fileExtension) const; |
125 | + Q_INVOKABLE bool link(const QString &from, const QString &to); |
126 | +}; |
127 | + |
128 | +#endif // FILEOPERATIONS_H |
129 | |
130 | === modified file 'src/messagingapplication.cpp' |
131 | --- src/messagingapplication.cpp 2015-11-23 19:51:16 +0000 |
132 | +++ src/messagingapplication.cpp 2015-12-08 18:33:04 +0000 |
133 | @@ -1,5 +1,5 @@ |
134 | /* |
135 | - * Copyright (C) 2012 Canonical, Ltd. |
136 | + * Copyright (C) 2012-2015 Canonical, Ltd. |
137 | * |
138 | * This file is part of messaging-app. |
139 | * |
140 | @@ -17,6 +17,7 @@ |
141 | */ |
142 | |
143 | #include "messagingapplication.h" |
144 | +#include "fileoperations.h" |
145 | |
146 | #include <libnotify/notify.h> |
147 | |
148 | @@ -65,12 +66,24 @@ |
149 | } |
150 | } |
151 | |
152 | +static QObject* FileOperations_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) |
153 | +{ |
154 | + Q_UNUSED(engine); |
155 | + Q_UNUSED(scriptEngine); |
156 | + return new FileOperations(); |
157 | +} |
158 | + |
159 | MessagingApplication::MessagingApplication(int &argc, char **argv) |
160 | : QGuiApplication(argc, argv), m_view(0), m_applicationIsReady(false) |
161 | { |
162 | setApplicationName("MessagingApp"); |
163 | } |
164 | |
165 | +bool MessagingApplication::fullscreen() const |
166 | +{ |
167 | + return m_view->windowState() == Qt::WindowFullScreen; |
168 | +} |
169 | + |
170 | bool MessagingApplication::setup() |
171 | { |
172 | installIconPath(); |
173 | @@ -133,6 +146,9 @@ |
174 | } |
175 | } |
176 | |
177 | + const char* uri = "messagingapp.private"; |
178 | + qmlRegisterSingletonType<FileOperations>(uri, 0, 1, "FileOperations", FileOperations_singleton_factory); |
179 | + |
180 | m_view = new QQuickView(); |
181 | QObject::connect(m_view, SIGNAL(statusChanged(QQuickView::Status)), this, SLOT(onViewStatusChanged(QQuickView::Status))); |
182 | QObject::connect(m_view->engine(), SIGNAL(quit()), SLOT(quit())); |
183 | @@ -176,6 +192,17 @@ |
184 | } |
185 | } |
186 | |
187 | +void MessagingApplication::setFullscreen(bool fullscreen) |
188 | +{ |
189 | + if (fullscreen) { |
190 | + m_view->setWindowState(Qt::WindowFullScreen); |
191 | + } else { |
192 | + m_view->setWindowState(Qt::WindowNoState); |
193 | + } |
194 | + |
195 | + Q_EMIT fullscreenChanged(); |
196 | +} |
197 | + |
198 | void MessagingApplication::onViewStatusChanged(QQuickView::Status status) |
199 | { |
200 | if (status != QQuickView::Ready) { |
201 | |
202 | === modified file 'src/messagingapplication.h' |
203 | --- src/messagingapplication.h 2015-11-18 16:36:51 +0000 |
204 | +++ src/messagingapplication.h 2015-12-08 18:33:04 +0000 |
205 | @@ -1,5 +1,5 @@ |
206 | /* |
207 | - * Copyright (C) 2012-2013 Canonical, Ltd. |
208 | + * Copyright (C) 2012-2015 Canonical, Ltd. |
209 | * |
210 | * This file is part of messaging-app. |
211 | * |
212 | @@ -26,13 +26,18 @@ |
213 | class MessagingApplication : public QGuiApplication |
214 | { |
215 | Q_OBJECT |
216 | + Q_PROPERTY(bool fullscreen READ fullscreen WRITE setFullscreen NOTIFY fullscreenChanged) |
217 | |
218 | public: |
219 | MessagingApplication(int &argc, char **argv); |
220 | virtual ~MessagingApplication(); |
221 | |
222 | + bool fullscreen() const; |
223 | bool setup(); |
224 | |
225 | +Q_SIGNALS: |
226 | + void fullscreenChanged(); |
227 | + |
228 | public Q_SLOTS: |
229 | void activateWindow(); |
230 | void parseArgument(const QString &arg); |
231 | @@ -41,6 +46,7 @@ |
232 | void showNotificationMessage(const QString &message, const QString &icon = QString()); |
233 | |
234 | private Q_SLOTS: |
235 | + void setFullscreen(bool fullscreen); |
236 | void onViewStatusChanged(QQuickView::Status status); |
237 | void onApplicationReady(); |
238 | |
239 | |
240 | === modified file 'src/qml/AttachmentPanel.qml' |
241 | --- src/qml/AttachmentPanel.qml 2015-12-08 18:33:04 +0000 |
242 | +++ src/qml/AttachmentPanel.qml 2015-12-08 18:33:04 +0000 |
243 | @@ -102,8 +102,7 @@ |
244 | } |
245 | } |
246 | |
247 | - // FIXME: re-enable that once we have proper delegates |
248 | - /*TransparentButton { |
249 | + TransparentButton { |
250 | id: videoButton |
251 | objectName: "videoButton" |
252 | iconName: "stock_video" |
253 | @@ -114,7 +113,7 @@ |
254 | onClicked: { |
255 | contentImporter.requestVideo() |
256 | } |
257 | - }*/ |
258 | + } |
259 | |
260 | // FIXME: enable generic file sharing if we ever support it |
261 | /*TransparentButton { |
262 | |
263 | === modified file 'src/qml/ComposeBar.qml' |
264 | --- src/qml/ComposeBar.qml 2015-12-08 18:33:04 +0000 |
265 | +++ src/qml/ComposeBar.qml 2015-12-08 18:33:04 +0000 |
266 | @@ -204,6 +204,8 @@ |
267 | return Qt.resolvedUrl("ThumbnailContact.qml") |
268 | case ContentType.Pictures: |
269 | return Qt.resolvedUrl("ThumbnailImage.qml") |
270 | + case ContentType.Videos: |
271 | + return Qt.resolvedUrl("ThumbnailVideo.qml") |
272 | case ContentType.Unknown: |
273 | return Qt.resolvedUrl("ThumbnailUnknown.qml") |
274 | default: |
275 | |
276 | === modified file 'src/qml/MMS/MMSImage.qml' |
277 | --- src/qml/MMS/MMSImage.qml 2015-09-14 13:51:27 +0000 |
278 | +++ src/qml/MMS/MMSImage.qml 2015-12-08 18:33:04 +0000 |
279 | @@ -34,6 +34,7 @@ |
280 | |
281 | image: Image { |
282 | id: imageAttachment |
283 | + objectName: "imageAttachment" |
284 | |
285 | fillMode: Image.PreserveAspectCrop |
286 | smooth: true |
287 | |
288 | === modified file 'src/qml/MMS/MMSVideo.qml' |
289 | --- src/qml/MMS/MMSVideo.qml 2015-09-14 13:51:27 +0000 |
290 | +++ src/qml/MMS/MMSVideo.qml 2015-12-08 18:33:04 +0000 |
291 | @@ -1,5 +1,5 @@ |
292 | /* |
293 | - * Copyright 2012, 2013, 2014 Canonical Ltd. |
294 | + * Copyright 2012-2015 Canonical Ltd. |
295 | * |
296 | * This file is part of messaging-app. |
297 | * |
298 | @@ -18,64 +18,80 @@ |
299 | |
300 | import QtQuick 2.2 |
301 | import Ubuntu.Components 1.3 |
302 | -import QtMultimedia 5.0 |
303 | -import ".." |
304 | +import Ubuntu.Thumbnailer 0.1 |
305 | |
306 | MMSBase { |
307 | id: videoDelegate |
308 | |
309 | previewer: "MMS/PreviewerVideo.qml" |
310 | - anchors.left: parent.left |
311 | - anchors.right: parent.right |
312 | - height: bubble.height + units.gu(1) |
313 | + height: videoAttachment.height |
314 | + width: videoAttachment.width |
315 | |
316 | - Item { |
317 | + UbuntuShape { |
318 | id: bubble |
319 | anchors.top: parent.top |
320 | - width: videoOutput.width + units.gu(3) |
321 | - height: videoOutput.height + units.gu(2) |
322 | - |
323 | - MediaPlayer { |
324 | - id: video |
325 | - autoLoad: true |
326 | - autoPlay: false |
327 | - source: attachment.filePath |
328 | - onStatusChanged: { |
329 | - if (status === MediaPlayer.Loaded) { |
330 | - // FIXME: there is no way to show the thumbnail |
331 | - video.play(); video.stop(); |
332 | - |
333 | - // resize videoOutput, as width is not set |
334 | - // properly when using PreserveAspectFit |
335 | - if (videoOutput.height > units.gu(25)) { |
336 | - var percentageResized = units.gu(25)*100/(metaData.resolution.height) |
337 | - videoOutput.height = units.gu(25) |
338 | - videoOutput.width = (metaData.resolution.width*percentageResized)/100 |
339 | - } |
340 | - if (videoOutput.width > units.gu(35)) { |
341 | - percentageResized = units.gu(35)*100/(metaData.resolution.width) |
342 | - videoOutput.width = units.gu(35) |
343 | - videoOutput.height = (metaData.resolution.height*percentageResized)/100 |
344 | - } |
345 | + width: image.width |
346 | + height: image.height |
347 | + |
348 | + image: Image { |
349 | + id: videoAttachment |
350 | + objectName: "videoAttachment" |
351 | + |
352 | + fillMode: Image.PreserveAspectCrop |
353 | + smooth: true |
354 | + source: "image://thumbnailer/" + attachment.filePath |
355 | + visible: false |
356 | + asynchronous: true |
357 | + height: Math.min(implicitHeight, units.gu(14)) |
358 | + width: Math.min(implicitWidth, units.gu(27)) |
359 | + cache: false |
360 | + |
361 | + sourceSize.width: units.gu(27) |
362 | + sourceSize.height: units.gu(27) |
363 | + |
364 | + onStatusChanged: { |
365 | + if (status === Image.Error) { |
366 | + source = "image://theme/image-missing" |
367 | + width = 128 |
368 | + height = 128 |
369 | } |
370 | } |
371 | } |
372 | - VideoOutput { |
373 | - id: videoOutput |
374 | - source: video |
375 | + |
376 | + Icon { |
377 | + objectName: "playbackStartIcon" |
378 | + width: units.gu(3) |
379 | + height: units.gu(3) |
380 | anchors.centerIn: parent |
381 | - anchors.horizontalCenterOffset: incoming ? units.gu(0.5) : -units.gu(0.5) |
382 | + name: "media-playback-start" |
383 | + color: "white" |
384 | + opacity: 0.8 |
385 | } |
386 | |
387 | Rectangle { |
388 | - color: "black" |
389 | - opacity: 0.8 |
390 | - anchors.fill: videoOutput |
391 | - Icon { |
392 | - name: "media-playback-start" |
393 | - width: units.gu(4) |
394 | - height: units.gu(4) |
395 | - anchors.centerIn: parent |
396 | + visible: videoDelegate.lastItem |
397 | + gradient: Gradient { |
398 | + GradientStop { position: 0.0; color: "transparent" } |
399 | + GradientStop { position: 1.0; color: "gray" } |
400 | + } |
401 | + |
402 | + anchors { |
403 | + bottom: parent.bottom |
404 | + left: parent.left |
405 | + right: parent.right |
406 | + } |
407 | + height: units.gu(2) |
408 | + radius: bubble.height * 0.1 |
409 | + Label { |
410 | + anchors{ |
411 | + left: parent.left |
412 | + bottom: parent.bottom |
413 | + leftMargin: incoming ? units.gu(2) : units.gu(1) |
414 | + bottomMargin: units.gu(0.5) |
415 | + } |
416 | + fontSize: "xx-small" |
417 | + text: Qt.formatTime(timestamp).toLowerCase() |
418 | + color: "white" |
419 | } |
420 | } |
421 | } |
422 | |
423 | === modified file 'src/qml/MMS/PreviewerImage.qml' |
424 | --- src/qml/MMS/PreviewerImage.qml 2015-09-14 13:51:27 +0000 |
425 | +++ src/qml/MMS/PreviewerImage.qml 2015-12-08 18:33:04 +0000 |
426 | @@ -1,5 +1,5 @@ |
427 | /* |
428 | - * Copyright 2012, 2013, 2014 Canonical Ltd. |
429 | + * Copyright 2012-2015 Canonical Ltd. |
430 | * |
431 | * This file is part of messaging-app. |
432 | * |
433 | @@ -19,18 +19,193 @@ |
434 | import QtQuick 2.2 |
435 | import Ubuntu.Components 1.3 |
436 | import Ubuntu.Content 0.1 |
437 | +import Ubuntu.Thumbnailer 0.1 |
438 | import ".." |
439 | |
440 | Previewer { |
441 | + id: imagePreviewer |
442 | + |
443 | + Component.onCompleted: application.fullscreen = true |
444 | + Component.onDestruction: application.fullscreen = false |
445 | + |
446 | + Connections { |
447 | + target: application |
448 | + onFullscreenChanged: imagePreviewer.head.visible = !application.fullscreen |
449 | + } |
450 | + |
451 | title: i18n.tr("Image Preview") |
452 | clip: true |
453 | - Image { |
454 | - anchors.centerIn: parent |
455 | + |
456 | + Rectangle { |
457 | anchors.fill: parent |
458 | - fillMode: Image.PreserveAspectFit |
459 | - source: attachment.filePath |
460 | - cache: false |
461 | - sourceSize.width: parent.width |
462 | - sourceSize.height: parent.height |
463 | + color: "black" |
464 | + } |
465 | + |
466 | + Item { |
467 | + id: imageItem |
468 | + property bool pinchInProgress: zoomPinchArea.active |
469 | + property size thumbSize: Qt.size(viewer.width * 1.05, viewer.height * 1.05) |
470 | + |
471 | + onWidthChanged: { |
472 | + // Only change thumbSize if width increases more than 5% |
473 | + // that way we do not reload image for small resizes |
474 | + if (width > thumbSize.width) { |
475 | + thumbSize = Qt.size(width * 1.05, height * 1.05); |
476 | + } |
477 | + } |
478 | + |
479 | + onHeightChanged: { |
480 | + // Only change thumbSize if height increases more than 5% |
481 | + // that way we do not reload image for small resizes |
482 | + if (height > thumbSize.height) { |
483 | + thumbSize = Qt.size(width * 1.05, height * 1.05); |
484 | + } |
485 | + } |
486 | + |
487 | + function zoomIn(centerX, centerY, factor) { |
488 | + flickable.scaleCenterX = centerX / (flickable.sizeScale * flickable.width); |
489 | + flickable.scaleCenterY = centerY / (flickable.sizeScale * flickable.height); |
490 | + flickable.sizeScale = factor; |
491 | + } |
492 | + |
493 | + function zoomOut() { |
494 | + if (flickable.sizeScale != 1.0) { |
495 | + flickable.scaleCenterX = flickable.contentX / flickable.width / (flickable.sizeScale - 1); |
496 | + flickable.scaleCenterY = flickable.contentY / flickable.height / (flickable.sizeScale - 1); |
497 | + flickable.sizeScale = 1.0; |
498 | + } |
499 | + } |
500 | + |
501 | + width: parent.width |
502 | + height: parent.height |
503 | + |
504 | + ActivityIndicator { |
505 | + objectName: "imageActivityIndicator" |
506 | + anchors.centerIn: parent |
507 | + visible: running |
508 | + running: image.status != Image.Ready |
509 | + } |
510 | + |
511 | + PinchArea { |
512 | + id: zoomPinchArea |
513 | + anchors.fill: parent |
514 | + |
515 | + property real initialZoom |
516 | + property real maximumScale: 3.0 |
517 | + property real minimumZoom: 1.0 |
518 | + property real maximumZoom: 3.0 |
519 | + property bool active: false |
520 | + property var center |
521 | + |
522 | + onPinchStarted: { |
523 | + active = true; |
524 | + initialZoom = flickable.sizeScale; |
525 | + center = zoomPinchArea.mapToItem(media, pinch.startCenter.x, pinch.startCenter.y); |
526 | + imageItem.zoomIn(center.x, center.y, initialZoom); |
527 | + } |
528 | + onPinchUpdated: { |
529 | + var zoomFactor = MathUtils.clamp(initialZoom * pinch.scale, minimumZoom, maximumZoom); |
530 | + flickable.sizeScale = zoomFactor; |
531 | + } |
532 | + onPinchFinished: { |
533 | + active = false; |
534 | + } |
535 | + |
536 | + Flickable { |
537 | + id: flickable |
538 | + anchors.fill: parent |
539 | + contentWidth: media.width |
540 | + contentHeight: media.height |
541 | + contentX: (sizeScale - 1) * scaleCenterX * width |
542 | + contentY: (sizeScale - 1) * scaleCenterY * height |
543 | + interactive: !imageItem.pinchInProgress |
544 | + |
545 | + property real sizeScale: 1.0 |
546 | + property real scaleCenterX: 0.0 |
547 | + property real scaleCenterY: 0.0 |
548 | + |
549 | + Behavior on sizeScale { |
550 | + enabled: !imageItem.pinchInProgress |
551 | + UbuntuNumberAnimation {duration: UbuntuAnimation.FastDuration} |
552 | + } |
553 | + Behavior on scaleCenterX { |
554 | + UbuntuNumberAnimation {duration: UbuntuAnimation.FastDuration} |
555 | + } |
556 | + Behavior on scaleCenterY { |
557 | + UbuntuNumberAnimation {duration: UbuntuAnimation.FastDuration} |
558 | + } |
559 | + |
560 | + Item { |
561 | + id: media |
562 | + |
563 | + width: flickable.width * flickable.sizeScale |
564 | + height: flickable.height * flickable.sizeScale |
565 | + |
566 | + Image { |
567 | + id: image |
568 | + objectName: "thumbnailImage" |
569 | + anchors.fill: parent |
570 | + asynchronous: true |
571 | + cache: false |
572 | + source: "image://thumbnailer/%1".arg(attachment.filePath.toString()) |
573 | + sourceSize { |
574 | + width: imageItem.thumbSize.width |
575 | + height: imageItem.thumbSize.height |
576 | + } |
577 | + fillMode: Image.PreserveAspectFit |
578 | + opacity: status == Image.Ready ? 1.0 : 0.0 |
579 | + Behavior on opacity { UbuntuNumberAnimation {duration: UbuntuAnimation.FastDuration} } |
580 | + } |
581 | + |
582 | + Image { |
583 | + id: highResolutionImage |
584 | + objectName: "highResolutionImage" |
585 | + anchors.fill: parent |
586 | + asynchronous: true |
587 | + cache: false |
588 | + source: flickable.sizeScale > 1.0 ? attachment.filePath : "" |
589 | + sourceSize { |
590 | + width: width |
591 | + height: height |
592 | + } |
593 | + fillMode: Image.PreserveAspectFit |
594 | + } |
595 | + } |
596 | + |
597 | + MouseArea { |
598 | + id: imageMouseArea |
599 | + anchors.fill: parent |
600 | + |
601 | + property bool clickAccepted: false |
602 | + |
603 | + onDoubleClicked: { |
604 | + if (imageMouseArea.clickAccepted) { |
605 | + return |
606 | + } |
607 | + |
608 | + clickTimer.stop() |
609 | + |
610 | + if (flickable.sizeScale < zoomPinchArea.maximumZoom) { |
611 | + imageItem.zoomIn(mouse.x, mouse.y, zoomPinchArea.maximumZoom); |
612 | + } else { |
613 | + imageItem.zoomOut(); |
614 | + } |
615 | + } |
616 | + onClicked: { |
617 | + imageMouseArea.clickAccepted = false |
618 | + clickTimer.start() |
619 | + } |
620 | + } |
621 | + |
622 | + Timer { |
623 | + id: clickTimer |
624 | + interval: 200 |
625 | + onTriggered: { |
626 | + imageMouseArea.clickAccepted = true |
627 | + application.fullscreen = !application.fullscreen |
628 | + } |
629 | + } |
630 | + } |
631 | + } |
632 | } |
633 | } |
634 | |
635 | === modified file 'src/qml/MMS/PreviewerVideo.qml' |
636 | --- src/qml/MMS/PreviewerVideo.qml 2015-09-14 13:51:27 +0000 |
637 | +++ src/qml/MMS/PreviewerVideo.qml 2015-12-08 18:33:04 +0000 |
638 | @@ -1,5 +1,5 @@ |
639 | /* |
640 | - * Copyright 2012, 2013, 2014 Canonical Ltd. |
641 | + * Copyright 2012-2015 Canonical Ltd. |
642 | * |
643 | * This file is part of messaging-app. |
644 | * |
645 | @@ -17,61 +17,152 @@ |
646 | */ |
647 | |
648 | import QtQuick 2.2 |
649 | +import QtMultimedia 5.0 |
650 | import Ubuntu.Components 1.3 |
651 | -import QtMultimedia 5.0 |
652 | +import Ubuntu.Content 0.1 |
653 | +import Ubuntu.Thumbnailer 0.1 |
654 | +import messagingapp.private 0.1 |
655 | import ".." |
656 | |
657 | Previewer { |
658 | + id: videoPreviewer |
659 | + |
660 | title: i18n.tr("Video Preview") |
661 | - // This previewer implements only basic video controls: play/pause/rewind |
662 | - onActionTriggered: video.pause() |
663 | - MediaPlayer { |
664 | - id: video |
665 | - autoLoad: true |
666 | - autoPlay: true |
667 | - source: attachment.filePath |
668 | - } |
669 | - VideoOutput { |
670 | - id: videoOutput |
671 | - source: video |
672 | - anchors.fill: parent |
673 | + clip: true |
674 | + |
675 | + Component.onCompleted: { |
676 | + application.fullscreen = true |
677 | + // Load Video player after toggling fullscreen to reduce flickering |
678 | + videoLoader.active = true |
679 | + } |
680 | + Component.onDestruction: application.fullscreen = false |
681 | + |
682 | + Connections { |
683 | + target: application |
684 | + onFullscreenChanged: { |
685 | + videoPreviewer.head.visible = !application.fullscreen |
686 | + toolbar.collapsed = application.fullscreen |
687 | + } |
688 | + } |
689 | + |
690 | + Rectangle { |
691 | + anchors.fill: parent |
692 | + color: "black" |
693 | + } |
694 | + |
695 | + Loader { |
696 | + id: videoLoader |
697 | + |
698 | + anchors.fill: parent |
699 | + active: false |
700 | + sourceComponent: videoComponent |
701 | + |
702 | + onStatusChanged: { |
703 | + if (status == Loader.Ready) { |
704 | + var tmpFile = FileOperations.getTemporaryFile(".mp4") |
705 | + if (FileOperations.link(attachment.filePath, tmpFile)) { |
706 | + videoLoader.item.source = tmpFile |
707 | + } else { |
708 | + console.log("MMSVideo: Failed to link", attachment.filePath, "to", tmpFile) |
709 | + } |
710 | + } |
711 | + } |
712 | + |
713 | + Component { |
714 | + id: videoComponent |
715 | + |
716 | + Item { |
717 | + id: videoPlayer |
718 | + objectName: "videoPlayer" |
719 | + |
720 | + property alias source: player.source |
721 | + property alias playbackState: player.playbackState |
722 | + |
723 | + function play() { player.play() } |
724 | + function pause() { player.pause() } |
725 | + function stop() { player.stop() } |
726 | + |
727 | + anchors.fill: parent |
728 | + |
729 | + MediaPlayer { |
730 | + id: player |
731 | + autoPlay: true |
732 | + } |
733 | + |
734 | + VideoOutput { |
735 | + id: videoOutput |
736 | + anchors.fill: parent |
737 | + source: player |
738 | + } |
739 | + } |
740 | + } |
741 | } |
742 | |
743 | MouseArea { |
744 | - id: playArea |
745 | - anchors.fill: parent |
746 | - onPressed: { |
747 | - if (video.playbackState === MediaPlayer.PlayingState) { |
748 | - video.pause() |
749 | - } |
750 | + anchors { |
751 | + top: parent.top |
752 | + bottom: toolbar.top |
753 | + left: parent.left |
754 | + right: parent.right |
755 | } |
756 | + onClicked: application.fullscreen = !application.fullscreen |
757 | } |
758 | |
759 | Rectangle { |
760 | - color: "black" |
761 | - visible: video.playbackState !== MediaPlayer.PlayingState |
762 | + id: toolbar |
763 | + objectName: "toolbar" |
764 | + |
765 | + property bool collapsed: false |
766 | + |
767 | + anchors.bottom: parent.bottom |
768 | + |
769 | + width: parent.width |
770 | + height: collapsed ? 0 : units.gu(7) |
771 | + Behavior on height { UbuntuNumberAnimation {} } |
772 | + |
773 | + color: "gray" |
774 | opacity: 0.8 |
775 | - anchors.fill: videoOutput |
776 | + |
777 | Row { |
778 | - anchors.centerIn: parent |
779 | + anchors { |
780 | + top: parent.top |
781 | + bottom: parent.bottom |
782 | + horizontalCenter: parent.horizontalCenter |
783 | + } |
784 | + |
785 | + spacing: units.gu(2) |
786 | + |
787 | Icon { |
788 | - name: "media-playback-pause" |
789 | - width: units.gu(5) |
790 | - height: units.gu(5) |
791 | + anchors.verticalCenter: parent.verticalCenter |
792 | + width: toolbar.collapsed ? 0 : units.gu(5) |
793 | + height: width |
794 | + Behavior on width { UbuntuNumberAnimation {} } |
795 | + Behavior on height { UbuntuNumberAnimation {} } |
796 | + name: videoLoader.item && videoLoader.item.playbackState == MediaPlayer.PlayingState ? "media-playback-pause" : "media-playback-start" |
797 | + color: "white" |
798 | MouseArea { |
799 | anchors.fill: parent |
800 | - onClicked: video.play(); |
801 | + onClicked: { |
802 | + if (videoLoader.item.playbackState == MediaPlayer.PlayingState) { |
803 | + videoLoader.item.pause() |
804 | + } else { |
805 | + videoLoader.item.play() |
806 | + } |
807 | + } |
808 | } |
809 | } |
810 | Icon { |
811 | - name: "media-seek-backward" |
812 | - width: units.gu(5) |
813 | - height: units.gu(5) |
814 | + anchors.verticalCenter: parent.verticalCenter |
815 | + width: toolbar.collapsed ? 0 : units.gu(5) |
816 | + height: width |
817 | + Behavior on width { UbuntuNumberAnimation {} } |
818 | + Behavior on height { UbuntuNumberAnimation {} } |
819 | + name: "media-playback-stop" |
820 | + color: "white" |
821 | MouseArea { |
822 | anchors.fill: parent |
823 | onClicked: { |
824 | - video.stop(); |
825 | - video.play(); |
826 | + videoLoader.item.stop() |
827 | } |
828 | } |
829 | } |
830 | |
831 | === modified file 'src/qml/MMSDelegate.qml' |
832 | --- src/qml/MMSDelegate.qml 2015-11-23 19:51:16 +0000 |
833 | +++ src/qml/MMSDelegate.qml 2015-12-08 18:33:04 +0000 |
834 | @@ -87,12 +87,6 @@ |
835 | "data": attachment, |
836 | "delegateSource": "MMS/MMSImage.qml", |
837 | }) |
838 | - //} else if (startsWith(attachment.contentType, "video/")) { |
839 | - // TODO: implement proper video attachment support |
840 | - // dataAttachments.push({type: "video", |
841 | - // data: attachment, |
842 | - // delegateSource: "MMS/MMSVideo.qml", |
843 | - // }) |
844 | } else if (startsWith(attachment.contentType, "application/smil") || |
845 | startsWith(attachment.contentType, "application/x-smil")) { |
846 | // smil files will always be ignored here |
847 | @@ -102,6 +96,11 @@ |
848 | "data": attachment, |
849 | "delegateSource": "MMS/MMSContact.qml" |
850 | }) |
851 | + } else if (startsWith(attachment.contentType, "video/")) { |
852 | + root.dataAttachments.push({"type": "video", |
853 | + "data": attachment, |
854 | + "delegateSource": "MMS/MMSVideo.qml", |
855 | + }) |
856 | } else { |
857 | root.dataAttachments.push({"type": "default", |
858 | "data": attachment, |
859 | @@ -221,7 +220,7 @@ |
860 | target: bubbleLoader.item |
861 | property: "sender" |
862 | value: messageData.sender.alias !== "" ? messageData.sender.alias : messageData.senderId |
863 | - when: participants.length > 1 && bubbleLoader.status === Loader.Ready && messageData.senderId !== "self" |
864 | + when: messageData.participants.length > 1 && bubbleLoader.status === Loader.Ready && messageData.senderId !== "self" |
865 | } |
866 | } |
867 | } |
868 | |
869 | === added file 'src/qml/ThumbnailVideo.qml' |
870 | --- src/qml/ThumbnailVideo.qml 1970-01-01 00:00:00 +0000 |
871 | +++ src/qml/ThumbnailVideo.qml 2015-12-08 18:33:04 +0000 |
872 | @@ -0,0 +1,76 @@ |
873 | +/* |
874 | + * Copyright 2015 Canonical Ltd. |
875 | + * |
876 | + * This file is part of messaging-app. |
877 | + * |
878 | + * messaging-app is free software; you can redistribute it and/or modify |
879 | + * it under the terms of the GNU General Public License as published by |
880 | + * the Free Software Foundation; version 3. |
881 | + * |
882 | + * messaging-app is distributed in the hope that it will be useful, |
883 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
884 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
885 | + * GNU General Public License for more details. |
886 | + * |
887 | + * You should have received a copy of the GNU General Public License |
888 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
889 | + */ |
890 | + |
891 | +import QtQuick 2.0 |
892 | +import Ubuntu.Components 1.3 |
893 | +import Ubuntu.Thumbnailer 0.1 |
894 | + |
895 | +UbuntuShape { |
896 | + id: thumbnail |
897 | + property int index |
898 | + property string filePath |
899 | + |
900 | + signal pressAndHold() |
901 | + |
902 | + onFilePathChanged: videoImage.source = "image://thumbnailer/" + filePath |
903 | + |
904 | + width: childrenRect.width |
905 | + height: childrenRect.height |
906 | + |
907 | + image: Image { |
908 | + id: videoImage |
909 | + |
910 | + width: units.gu(8) |
911 | + height: units.gu(8) |
912 | + sourceSize.width: width |
913 | + sourceSize.height: height |
914 | + fillMode: Image.PreserveAspectCrop |
915 | + asynchronous: true |
916 | + |
917 | + onStatusChanged: { |
918 | + if (status === Image.Error) { |
919 | + source = "image://theme/image-missing" |
920 | + } |
921 | + } |
922 | + } |
923 | + |
924 | + ActivityIndicator { |
925 | + anchors.centerIn: parent |
926 | + visible: running |
927 | + running: videoImage.status != Image.Ready |
928 | + } |
929 | + |
930 | + Icon { |
931 | + width: units.gu(3) |
932 | + height: units.gu(3) |
933 | + anchors.centerIn: parent |
934 | + name: "media-playback-start" |
935 | + color: "white" |
936 | + visible: opacity > 0.0 |
937 | + opacity: videoImage.status == Image.Ready ? 0.8 : 0.0 |
938 | + Behavior on opacity { UbuntuNumberAnimation {duration: UbuntuAnimation.FastDuration} } |
939 | + } |
940 | + |
941 | + MouseArea { |
942 | + anchors.fill: parent |
943 | + onPressAndHold: { |
944 | + mouse.accept = true |
945 | + thumbnail.pressAndHold() |
946 | + } |
947 | + } |
948 | +} |
949 | |
950 | === modified file 'src/qml/messaging-app.qml' |
951 | --- src/qml/messaging-app.qml 2015-11-23 19:51:16 +0000 |
952 | +++ src/qml/messaging-app.qml 2015-12-08 18:33:04 +0000 |
953 | @@ -1,5 +1,5 @@ |
954 | /* |
955 | - * Copyright 2012-2013 Canonical Ltd. |
956 | + * Copyright 2012-2015 Canonical Ltd. |
957 | * |
958 | * This file is part of messaging-app. |
959 | * |
960 | @@ -194,6 +194,8 @@ |
961 | } else if (startsWith(contentType, "text/vcard") || |
962 | startsWith(contentType, "text/x-vcard")) { |
963 | return ContentType.Contacts |
964 | + } else if (startsWith(contentType, "video/")) { |
965 | + return ContentType.Videos |
966 | } |
967 | return ContentType.Unknown |
968 | } |
969 | |
970 | === modified file 'tests/qml/CMakeLists.txt' |
971 | --- tests/qml/CMakeLists.txt 2015-08-13 18:34:55 +0000 |
972 | +++ tests/qml/CMakeLists.txt 2015-12-08 18:33:04 +0000 |
973 | @@ -1,33 +1,42 @@ |
974 | -find_program(QMLTESTRUNNER_BIN |
975 | - NAMES qmltestrunner |
976 | - PATHS /usr/lib/*/qt5/bin |
977 | - NO_DEFAULT_PATH |
978 | -) |
979 | +find_package(Qt5Core REQUIRED) |
980 | +find_package(Qt5Qml REQUIRED) |
981 | +find_package(Qt5Quick REQUIRED) |
982 | +find_package(Qt5QuickTest REQUIRED) |
983 | + |
984 | +set(XVFB_COMMAND) |
985 | |
986 | find_program(XVFB_RUN_BIN |
987 | NAMES xvfb-run |
988 | ) |
989 | |
990 | -macro(DECLARE_QML_TEST TST_NAME TST_QML_FILE) |
991 | - add_test(NAME ${TST_NAME} |
992 | - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} |
993 | - COMMAND ${XVFB_RUN_BIN} -a -s "-screen 0 1024x768x24" ${QMLTESTRUNNER_BIN} -import ${qml_BINARY_DIR} -input ${CMAKE_CURRENT_SOURCE_DIR}/${TST_QML_FILE} |
994 | - ) |
995 | -endmacro() |
996 | - |
997 | -if(QMLTESTRUNNER_BIN AND XVFB_RUN_BIN) |
998 | - declare_qml_test("message_bubble" tst_MessageBubble.qml) |
999 | - declare_qml_test("messages_view" tst_MessagesView.qml) |
1000 | +if(XVFB_RUN_BIN) |
1001 | + set(XVFB_COMMAND ${XVFB_RUN_BIN} -s "-screen 0 1024x768x24" -a) |
1002 | else() |
1003 | - if (NOT QMLTESTRUNNER_BIN) |
1004 | - message(WARNING "Qml tests disabled: qmltestrunner not found") |
1005 | - else() |
1006 | - message(WARNING "Qml tests disabled: xvfb-run not found") |
1007 | - endif() |
1008 | + message(WARNING "Qml tests disabled: xvfb-run not found") |
1009 | endif() |
1010 | |
1011 | -set(QML_TST_FILES |
1012 | - tst_MessageBubble.qml |
1013 | - tst_MessagesView.qml |
1014 | -) |
1015 | -add_custom_target(tst_QmlFiles ALL SOURCES ${QML_TST_FILES}) |
1016 | +set(TEST tst_QmlTests) |
1017 | + |
1018 | +set(SOURCES |
1019 | + ${messaging-app_SOURCE_DIR}/src/fileoperations.cpp |
1020 | + tst_QmlTests.cpp |
1021 | +) |
1022 | + |
1023 | +add_executable(${TEST} ${SOURCES}) |
1024 | + |
1025 | +include_directories( |
1026 | + ${messaging-app_SOURCE_DIR}/src |
1027 | + ${CMAKE_CURRENT_BINARY_DIR} |
1028 | + ${CMAKE_CURRENT_SOURCE_DIR} |
1029 | +) |
1030 | + |
1031 | +target_link_libraries(${TEST} |
1032 | + Qt5::Core |
1033 | + Qt5::Qml |
1034 | + Qt5::Quick |
1035 | + Qt5::QuickTest |
1036 | +) |
1037 | + |
1038 | +add_test(${TEST} ${XVFB_COMMAND} ${CMAKE_CURRENT_BINARY_DIR}/${TEST} |
1039 | + -input ${CMAKE_CURRENT_SOURCE_DIR} |
1040 | + -import ${CMAKE_BINARY_DIR}/src) |
1041 | |
1042 | === added directory 'tests/qml/data' |
1043 | === added file 'tests/qml/data/sample.mp4' |
1044 | Binary files tests/qml/data/sample.mp4 1970-01-01 00:00:00 +0000 and tests/qml/data/sample.mp4 2015-12-08 18:33:04 +0000 differ |
1045 | === added file 'tests/qml/data/sample.png' |
1046 | Binary files tests/qml/data/sample.png 1970-01-01 00:00:00 +0000 and tests/qml/data/sample.png 2015-12-08 18:33:04 +0000 differ |
1047 | === added file 'tests/qml/tst_MMSDelegate.qml' |
1048 | --- tests/qml/tst_MMSDelegate.qml 1970-01-01 00:00:00 +0000 |
1049 | +++ tests/qml/tst_MMSDelegate.qml 2015-12-08 18:33:04 +0000 |
1050 | @@ -0,0 +1,167 @@ |
1051 | +/* |
1052 | + * Copyright 2015 Canonical Ltd. |
1053 | + * |
1054 | + * Authors: |
1055 | + * Arthur Mello <arthur.mello@canonical.com> |
1056 | + * |
1057 | + * This file is part of messaging-app. |
1058 | + * |
1059 | + * messaging-app is free software; you can redistribute it and/or modify |
1060 | + * it under the terms of the GNU General Public License as published by |
1061 | + * the Free Software Foundation; version 3. |
1062 | + * |
1063 | + * messaging-app is distributed in the hope that it will be useful, |
1064 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1065 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1066 | + * GNU General Public License for more details. |
1067 | + * |
1068 | + * You should have received a copy of the GNU General Public License |
1069 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1070 | + */ |
1071 | + |
1072 | +import QtQuick 2.2 |
1073 | +import QtTest 1.0 |
1074 | +import Ubuntu.Test 0.1 |
1075 | + |
1076 | +import '../../src/qml/' |
1077 | + |
1078 | +Item { |
1079 | + id: root |
1080 | + |
1081 | + width: units.gu(40) |
1082 | + height: units.gu(40) |
1083 | + |
1084 | + MMSDelegate { |
1085 | + id: mmsDelegate |
1086 | + objectName: "mmsDelegate" |
1087 | + |
1088 | + function startsWith(str, prefix) { |
1089 | + return str.toLowerCase().slice(0, prefix.length) === prefix.toLowerCase(); |
1090 | + } |
1091 | + |
1092 | + anchors.fill: parent |
1093 | + |
1094 | + messageData: { |
1095 | + "participants": [], |
1096 | + "sender": {"alias": ""}, |
1097 | + "textMessageAttachments": [], |
1098 | + } |
1099 | + } |
1100 | + |
1101 | + UbuntuTestCase { |
1102 | + id: mmsImageDelegateTestCase |
1103 | + name: 'mmsImageDelegateTestCase' |
1104 | + |
1105 | + when: windowShown |
1106 | + |
1107 | + function test_load_image() { |
1108 | + mmsDelegate.messageData = { |
1109 | + "newEvent": false, |
1110 | + "participants": [], |
1111 | + "sender": {"alias": ""}, |
1112 | + "senderId": "self", |
1113 | + "textMessage": "Message Delegate QML Test", |
1114 | + "textMessageAttachments": [ |
1115 | + { |
1116 | + "contentType": "image/png", |
1117 | + "filePath": Qt.resolvedUrl("./data/sample.png") |
1118 | + } |
1119 | + ], |
1120 | + "textMessageStatus": 1, |
1121 | + "textReadTimestamp": new Date(), |
1122 | + "timestamp": new Date() |
1123 | + } |
1124 | + |
1125 | + var image = findChild(mmsDelegate, "imageAttachment") |
1126 | + verify(image != null) |
1127 | + waitForRendering(image) |
1128 | + verify(image.source != "image://theme/image-missing") |
1129 | + } |
1130 | + |
1131 | + function test_load_invalid_path() { |
1132 | + mmsDelegate.messageData = { |
1133 | + "newEvent": false, |
1134 | + "participants": [], |
1135 | + "sender": {"alias": ""}, |
1136 | + "senderId": "self", |
1137 | + "textMessage": "Message Delegate QML Test", |
1138 | + "textMessageAttachments": [ |
1139 | + { |
1140 | + "contentType": "image/png", |
1141 | + "filePath": "/wrong/path/file.png" |
1142 | + } |
1143 | + ], |
1144 | + "textMessageStatus": 1, |
1145 | + "textReadTimestamp": new Date(), |
1146 | + "timestamp": new Date() |
1147 | + } |
1148 | + |
1149 | + var image = findChild(mmsDelegate, "imageAttachment") |
1150 | + verify(image != null) |
1151 | + waitForRendering(image) |
1152 | + compare(image.source, "image://theme/image-missing") |
1153 | + } |
1154 | + } |
1155 | + |
1156 | + UbuntuTestCase { |
1157 | + id: mmsVideoDelegateTestCase |
1158 | + name: 'mmsVideoDelegateTestCase' |
1159 | + |
1160 | + when: windowShown |
1161 | + |
1162 | + |
1163 | + function test_load_video() { |
1164 | + mmsDelegate.messageData = { |
1165 | + "newEvent": false, |
1166 | + "participants": [], |
1167 | + "sender": {"alias": ""}, |
1168 | + "senderId": "self", |
1169 | + "textMessage": "Message Delegate QML Test", |
1170 | + "textMessageAttachments": [ |
1171 | + { |
1172 | + "contentType": "video/mp4", |
1173 | + "filePath": Qt.resolvedUrl("./data/sample.mp4") |
1174 | + } |
1175 | + ], |
1176 | + "textMessageStatus": 1, |
1177 | + "textReadTimestamp": new Date(), |
1178 | + "timestamp": new Date() |
1179 | + } |
1180 | + |
1181 | + var video = findChild(mmsDelegate, "videoAttachment") |
1182 | + verify(video != null) |
1183 | + waitForRendering(video) |
1184 | + verify(video.source != "image://theme/image-missing") |
1185 | + |
1186 | + var icon = findChild(mmsDelegate, "playbackStartIcon") |
1187 | + verify(icon != null) |
1188 | + waitForRendering(icon) |
1189 | + verify(icon.visible) |
1190 | + } |
1191 | + |
1192 | + function test_load_invalid_path() { |
1193 | + skip("image://thumbnailer is not reporting an error for wrong file path") |
1194 | + mmsDelegate.messageData = { |
1195 | + "newEvent": false, |
1196 | + "participants": [], |
1197 | + "sender": {"alias": ""}, |
1198 | + "senderId": "self", |
1199 | + "textMessage": "Message Delegate QML Test", |
1200 | + "textMessageAttachments": [ |
1201 | + { |
1202 | + "contentType": "video/mp4", |
1203 | + "filePath": "/wrong/path/file.mp4" |
1204 | + } |
1205 | + ], |
1206 | + "textMessageStatus": 1, |
1207 | + "textReadTimestamp": new Date(), |
1208 | + "timestamp": new Date() |
1209 | + } |
1210 | + |
1211 | + var video = findChild(mmsDelegate, "videoAttachment") |
1212 | + verify(video != null) |
1213 | + waitForRendering(video) |
1214 | + compare(video.source, "image://theme/image-missing") |
1215 | + } |
1216 | + } |
1217 | +} |
1218 | |
1219 | === added file 'tests/qml/tst_PreviewerImage.qml' |
1220 | --- tests/qml/tst_PreviewerImage.qml 1970-01-01 00:00:00 +0000 |
1221 | +++ tests/qml/tst_PreviewerImage.qml 2015-12-08 18:33:04 +0000 |
1222 | @@ -0,0 +1,103 @@ |
1223 | +/* |
1224 | + * Copyright 2015 Canonical Ltd. |
1225 | + * |
1226 | + * Authors: |
1227 | + * Arthur Mello <arthur.mello@canonical.com> |
1228 | + * |
1229 | + * This file is part of messaging-app. |
1230 | + * |
1231 | + * messaging-app is free software; you can redistribute it and/or modify |
1232 | + * it under the terms of the GNU General Public License as published by |
1233 | + * the Free Software Foundation; version 3. |
1234 | + * |
1235 | + * messaging-app is distributed in the hope that it will be useful, |
1236 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1237 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1238 | + * GNU General Public License for more details. |
1239 | + * |
1240 | + * You should have received a copy of the GNU General Public License |
1241 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1242 | + */ |
1243 | + |
1244 | +import QtQuick 2.2 |
1245 | +import QtTest 1.0 |
1246 | +import Ubuntu.Test 0.1 |
1247 | + |
1248 | +import '../../src/qml/MMS' |
1249 | + |
1250 | +Item { |
1251 | + id: root |
1252 | + |
1253 | + width: units.gu(40) |
1254 | + height: units.gu(40) |
1255 | + |
1256 | + PreviewerImage { |
1257 | + id: previewerImage |
1258 | + objectName: "previewerImage" |
1259 | + |
1260 | + property var application: QtObject { |
1261 | + property bool fullscreen: false |
1262 | + } |
1263 | + |
1264 | + anchors.fill: parent |
1265 | + |
1266 | + attachment: { |
1267 | + "contentType": "image/png", |
1268 | + "filePath": Qt.resolvedUrl("./data/sample.png") |
1269 | + } |
1270 | + } |
1271 | + |
1272 | + UbuntuTestCase { |
1273 | + id: previewerImageTestCase |
1274 | + name: 'peviewerImageTestCase' |
1275 | + |
1276 | + when: windowShown |
1277 | + |
1278 | + function test_load_image() { |
1279 | + var activityIndicator = findChild(previewerImage, "imageActivityIndicator") |
1280 | + verify(activityIndicator != null) |
1281 | + tryCompare(activityIndicator, "visible", false) |
1282 | + |
1283 | + var thumbnail = findChild(previewerImage, "thumbnailImage") |
1284 | + verify(thumbnail != null) |
1285 | + tryCompare(thumbnail, "opacity", 1.0) |
1286 | + |
1287 | + var highRes = findChild(previewerImage, "highResolutionImage") |
1288 | + verify(highRes != null) |
1289 | + compare(highRes.source, "") |
1290 | + } |
1291 | + |
1292 | + function test_zoom_in_out() { |
1293 | + var activityIndicator = findChild(previewerImage, "imageActivityIndicator") |
1294 | + verify(activityIndicator != null) |
1295 | + tryCompare(activityIndicator, "visible", false) |
1296 | + |
1297 | + var thumbnail = findChild(previewerImage, "thumbnailImage") |
1298 | + verify(thumbnail != null) |
1299 | + tryCompare(thumbnail, "opacity", 1.0) |
1300 | + |
1301 | + var highRes = findChild(previewerImage, "highResolutionImage") |
1302 | + verify(highRes != null) |
1303 | + compare(highRes.source, "") |
1304 | + |
1305 | + mouseDoubleClick(thumbnail) |
1306 | + verify(highRes.source !== "") |
1307 | + |
1308 | + mouseDoubleClick(thumbnail) |
1309 | + compare(highRes.source, "") |
1310 | + } |
1311 | + |
1312 | + function test_toggle_fullscreen() { |
1313 | + var activityIndicator = findChild(previewerImage, "imageActivityIndicator") |
1314 | + verify(activityIndicator != null) |
1315 | + tryCompare(activityIndicator, "visible", false) |
1316 | + |
1317 | + var thumbnail = findChild(previewerImage, "thumbnailImage") |
1318 | + verify(thumbnail != null) |
1319 | + |
1320 | + verify(previewerImage.application.fullscreen) |
1321 | + mouseClick(thumbnail) |
1322 | + tryCompare(previewerImage.application, "fullscreen", false) |
1323 | + } |
1324 | + } |
1325 | +} |
1326 | |
1327 | === added file 'tests/qml/tst_PreviewerVideo.qml' |
1328 | --- tests/qml/tst_PreviewerVideo.qml 1970-01-01 00:00:00 +0000 |
1329 | +++ tests/qml/tst_PreviewerVideo.qml 2015-12-08 18:33:04 +0000 |
1330 | @@ -0,0 +1,87 @@ |
1331 | +/* |
1332 | + * Copyright 2015 Canonical Ltd. |
1333 | + * |
1334 | + * Authors: |
1335 | + * Arthur Mello <arthur.mello@canonical.com> |
1336 | + * |
1337 | + * This file is part of messaging-app. |
1338 | + * |
1339 | + * messaging-app is free software; you can redistribute it and/or modify |
1340 | + * it under the terms of the GNU General Public License as published by |
1341 | + * the Free Software Foundation; version 3. |
1342 | + * |
1343 | + * messaging-app is distributed in the hope that it will be useful, |
1344 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1345 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1346 | + * GNU General Public License for more details. |
1347 | + * |
1348 | + * You should have received a copy of the GNU General Public License |
1349 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1350 | + */ |
1351 | + |
1352 | +import QtQuick 2.2 |
1353 | +import QtTest 1.0 |
1354 | +import Ubuntu.Content 0.1 |
1355 | +import Ubuntu.Test 0.1 |
1356 | + |
1357 | +import '../../src/qml/MMS' |
1358 | + |
1359 | +Item { |
1360 | + id: root |
1361 | + |
1362 | + width: units.gu(40) |
1363 | + height: units.gu(40) |
1364 | + |
1365 | + PreviewerVideo { |
1366 | + id: previewerVideo |
1367 | + objectName: "previewerVideo" |
1368 | + |
1369 | + property var application: QtObject { |
1370 | + property bool fullscreen: false |
1371 | + } |
1372 | + |
1373 | + function getContentType(filePath) { |
1374 | + return ContentType.Videos |
1375 | + } |
1376 | + |
1377 | + anchors.fill: parent |
1378 | + |
1379 | + attachment: { |
1380 | + "contentType": "video/mp4", |
1381 | + "filePath": Qt.resolvedUrl("./data/sample.mp4") |
1382 | + } |
1383 | + } |
1384 | + |
1385 | + UbuntuTestCase { |
1386 | + id: previewerVideoTestCase |
1387 | + name: 'peviewerVideoTestCase' |
1388 | + |
1389 | + when: windowShown |
1390 | + |
1391 | + function test_load_video() { |
1392 | + var videoPlayer = findChild(previewerVideo, "videoPlayer") |
1393 | + verify(videoPlayer != null) |
1394 | + tryCompare(videoPlayer, "visible", true) |
1395 | + |
1396 | + var toolbar = findChild(previewerVideo, "toolbar") |
1397 | + verify(toolbar != null) |
1398 | + tryCompare(toolbar, "collapsed", true) |
1399 | + } |
1400 | + |
1401 | + function test_toggle_toolbar() { |
1402 | + var videoPlayer = findChild(previewerVideo, "videoPlayer") |
1403 | + verify(videoPlayer != null) |
1404 | + tryCompare(videoPlayer, "visible", true) |
1405 | + |
1406 | + var toolbar = findChild(previewerVideo, "toolbar") |
1407 | + verify(toolbar != null) |
1408 | + tryCompare(toolbar, "collapsed", true) |
1409 | + |
1410 | + mouseClick(videoPlayer) |
1411 | + tryCompare(toolbar, "collapsed", false) |
1412 | + |
1413 | + mouseClick(videoPlayer) |
1414 | + tryCompare(toolbar, "collapsed", true) |
1415 | + } |
1416 | + } |
1417 | +} |
1418 | |
1419 | === added file 'tests/qml/tst_QmlTests.cpp' |
1420 | --- tests/qml/tst_QmlTests.cpp 1970-01-01 00:00:00 +0000 |
1421 | +++ tests/qml/tst_QmlTests.cpp 2015-12-08 18:33:04 +0000 |
1422 | @@ -0,0 +1,61 @@ |
1423 | +/* |
1424 | + * Copyright (C) 2015 Canonical, Ltd. |
1425 | + * |
1426 | + * Authors: |
1427 | + * Arthur Mello <arthur.mello@canonical.com> |
1428 | + * |
1429 | + * This file is part of messaging-app. |
1430 | + * |
1431 | + * messaging-app is free software; you can redistribute it and/or modify |
1432 | + * it under the terms of the GNU General Public License as published by |
1433 | + * the Free Software Foundation; version 3. |
1434 | + * |
1435 | + * messaging-app is distributed in the hope that it will be useful, |
1436 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1437 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1438 | + * GNU General Public License for more details. |
1439 | + * |
1440 | + * You should have received a copy of the GNU General Public License |
1441 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1442 | + */ |
1443 | + |
1444 | +// Qt |
1445 | +#include <QtQuickTest/QtQuickTest> |
1446 | +#include <QtQml/QtQml> |
1447 | + |
1448 | +// local |
1449 | +#include "fileoperations.h" |
1450 | + |
1451 | +class TestContext : public QObject |
1452 | +{ |
1453 | + Q_OBJECT |
1454 | + |
1455 | +public: |
1456 | + explicit TestContext(QObject* parent=0) |
1457 | + : QObject(parent) |
1458 | + {} |
1459 | +}; |
1460 | + |
1461 | +static QObject* TestContext_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) |
1462 | +{ |
1463 | + Q_UNUSED(engine); |
1464 | + Q_UNUSED(scriptEngine); |
1465 | + return new TestContext(); |
1466 | +} |
1467 | + |
1468 | +static QObject* FileOperations_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) |
1469 | +{ |
1470 | + Q_UNUSED(engine); |
1471 | + Q_UNUSED(scriptEngine); |
1472 | + return new FileOperations(); |
1473 | +} |
1474 | + |
1475 | +int main(int argc, char** argv) |
1476 | +{ |
1477 | + qmlRegisterSingletonType<FileOperations>("messagingapp.private", 0, 1, "FileOperations", FileOperations_singleton_factory); |
1478 | + qmlRegisterSingletonType<TestContext>("messagingtest.private", 0, 1, "TestContext", TestContext_singleton_factory); |
1479 | + |
1480 | + return quick_test_main(argc, argv, "QmlTests", 0); |
1481 | +} |
1482 | + |
1483 | +#include "tst_QmlTests.moc" |
FAILED: Continuous integration, rev:476 jenkins. qa.ubuntu. com/job/ messaging- app-ci/ 749/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 5392/console jenkins. qa.ubuntu. com/job/ messaging- app-vivid- i386-ci/ 258/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 5406/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/messaging- app-ci/ 749/rebuild
http://