Merge lp:~fboucault/camera-app/async_lib_loading into lp:camera-app

Proposed by Florian Boucault
Status: Merged
Approved by: Bill Filler
Approved revision: 485
Merged at revision: 473
Proposed branch: lp:~fboucault/camera-app/async_lib_loading
Merge into: lp:camera-app
Diff against target: 658 lines (+233/-109)
10 files modified
CameraApp/foldersmodel.cpp (+113/-61)
CameraApp/foldersmodel.h (+19/-3)
GalleryView.qml (+39/-1)
GalleryViewLoader.qml (+5/-0)
PhotogridView.qml (+1/-6)
SlideshowView.qml (+6/-0)
ViewFinderView.qml (+11/-10)
camera-app.qml (+8/-2)
po/camera-app.pot (+26/-22)
tests/autopilot/camera_app/tests/test_gallery_view.py (+5/-4)
To merge this branch: bzr merge lp:~fboucault/camera-app/async_lib_loading
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Ubuntu Phablet Team Pending
Review via email: mp+247485@code.launchpad.net

Commit message

Asynchronously scan the filesystem for media. Fixes freeze at startup with a huge amount of media.
Significantly faster deletion when deleting a huge amount of media.
Taking a photo is now always fast even with a huge amount of media.

To post a comment you must log in.
474. By Florian Boucault

Faster scanning.

475. By Florian Boucault

Sorting is still important.

476. By Florian Boucault

Reverted pointless change

477. By Florian Boucault

Do not scan until FoldersModel is fully instantiated.

478. By Florian Boucault

Clear model immediately when updating.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
479. By Florian Boucault

Vastly more efficient selectAll with large collections.

480. By Florian Boucault

Fixed deletion bug.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
481. By Florian Boucault

Do not monitor for added file anylonger, instead manually prepend new media files shot. Depends on fix in qtubuntu-camera https://code.launchpad.net/~fboucault/qtubuntu-camera/fix_video_location/+merge/247507

482. By Florian Boucault

Significantly faster deletion of selected files.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
483. By Florian Boucault

Added feedback while media scanning is in progress.

484. By Florian Boucault

Updated pot file.

485. By Florian Boucault

Fixed autopilot tests.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CameraApp/foldersmodel.cpp'
--- CameraApp/foldersmodel.cpp 2014-11-26 14:45:34 +0000
+++ CameraApp/foldersmodel.cpp 2015-01-24 18:49:40 +0000
@@ -18,14 +18,26 @@
18#include <QtCore/QDir>18#include <QtCore/QDir>
19#include <QtCore/QUrl>19#include <QtCore/QUrl>
20#include <QtCore/QDateTime>20#include <QtCore/QDateTime>
21#include <QtCore/QFuture>
22#include <QtCore/QFutureWatcher>
23#include <QtCore/QtAlgorithms>
24#include <QtConcurrent/QtConcurrentRun>
25
26bool newerThan(const QFileInfo& fileInfo1, const QFileInfo& fileInfo2)
27{
28 return fileInfo1.lastModified() > fileInfo2.lastModified();
29}
30
2131
22FoldersModel::FoldersModel(QObject *parent) :32FoldersModel::FoldersModel(QObject *parent) :
23 QAbstractListModel(parent),33 QAbstractListModel(parent),
24 m_singleSelectionOnly(true)34 m_singleSelectionOnly(true),
35 m_completed(false),
36 m_loading(false)
25{37{
26 m_watcher = new QFileSystemWatcher(this);38 m_watcher = new QFileSystemWatcher(this);
27 connect(m_watcher, SIGNAL(directoryChanged(QString)), this, SLOT(directoryChanged(QString)));
28 connect(m_watcher, SIGNAL(fileChanged(QString)), this, SLOT(fileChanged(QString)));39 connect(m_watcher, SIGNAL(fileChanged(QString)), this, SLOT(fileChanged(QString)));
40 connect(&m_updateFutureWatcher, SIGNAL(finished()), this, SLOT(updateFileInfoListFinished()));
29}41}
3042
31QStringList FoldersModel::folders() const43QStringList FoldersModel::folders() const
@@ -80,31 +92,70 @@
80 return m_fileInfoList.count();92 return m_fileInfoList.count();
81}93}
8294
95bool FoldersModel::loading() const
96{
97 return m_loading;
98}
99
83void FoldersModel::updateFileInfoList()100void FoldersModel::updateFileInfoList()
84{101{
102 if (!m_completed) {
103 return;
104 }
105
106 m_loading = true;
107 Q_EMIT loadingChanged();
108
85 beginResetModel();109 beginResetModel();
86 m_fileInfoList.clear();110 m_fileInfoList.clear();
87 Q_FOREACH (QString folder, m_folders) {111 endResetModel();
112 m_selectedFiles.clear();
113 Q_EMIT selectedFilesChanged();
114 Q_EMIT countChanged();
115
116 m_updateFutureWatcher.cancel();
117 QFuture<QPair<QFileInfoList, QStringList> > future = QtConcurrent::run(this, &FoldersModel::computeFileInfoList, m_folders);
118 m_updateFutureWatcher.setFuture(future);
119}
120
121QPair<QFileInfoList, QStringList> FoldersModel::computeFileInfoList(QStringList folders)
122{
123 QFileInfoList filteredFileInfoList;
124 QStringList filesToWatch;
125
126 Q_FOREACH (QString folder, folders) {
88 QDir currentDir(folder);127 QDir currentDir(folder);
89 QFileInfoList fileInfoList = currentDir.entryInfoList(QDir::Files | QDir::Readable,128 QFileInfoList fileInfoList = currentDir.entryInfoList(QDir::Files | QDir::Readable,
90 QDir::Time | QDir::Reversed);129 QDir::Time | QDir::Reversed);
91 Q_FOREACH (QFileInfo fileInfo, fileInfoList) {130 Q_FOREACH (QFileInfo fileInfo, fileInfoList) {
92 if (fileInfo.isDir()) continue;131 filesToWatch.append(fileInfo.absoluteFilePath());
93 m_watcher->addPath(fileInfo.absoluteFilePath());
94 if (fileMatchesTypeFilters(fileInfo)) {132 if (fileMatchesTypeFilters(fileInfo)) {
95 insertFileInfo(fileInfo, false);133 filteredFileInfoList.append(fileInfo);
96 }134 }
97 }135 }
98 }136 }
137 qSort(filteredFileInfoList.begin(), filteredFileInfoList.end(), newerThan);
138 return QPair<QFileInfoList, QStringList>(filteredFileInfoList, filesToWatch);
139}
140
141void FoldersModel::updateFileInfoListFinished()
142{
143 QPair<QFileInfoList, QStringList> result = m_updateFutureWatcher.result();
144 setFileInfoList(result.first, result.second);
145}
146
147void FoldersModel::setFileInfoList(const QFileInfoList& fileInfoList, const QStringList& filesToWatch)
148{
149 beginResetModel();
150 m_fileInfoList = fileInfoList;
99 endResetModel();151 endResetModel();
100 m_selectedFiles.clear();152
153 // Start monitoring files for modifications in a separate thread as it is very time consuming
154 QtConcurrent::run(m_watcher, &QFileSystemWatcher::addPaths, filesToWatch);
155
156 m_loading = false;
157 Q_EMIT loadingChanged();
101 Q_EMIT countChanged();158 Q_EMIT countChanged();
102 Q_EMIT selectedFilesChanged();
103}
104
105bool moreRecentThan(const QFileInfo& fileInfo1, const QFileInfo& fileInfo2)
106{
107 return fileInfo1.lastModified() < fileInfo2.lastModified();
108}159}
109160
110bool FoldersModel::fileMatchesTypeFilters(const QFileInfo& newFileInfo)161bool FoldersModel::fileMatchesTypeFilters(const QFileInfo& newFileInfo)
@@ -120,33 +171,25 @@
120171
121// inserts newFileInfo into m_fileInfoList while keeping m_fileInfoList sorted by172// inserts newFileInfo into m_fileInfoList while keeping m_fileInfoList sorted by
122// file modification time with the files most recently modified first173// file modification time with the files most recently modified first
123void FoldersModel::insertFileInfo(const QFileInfo& newFileInfo, bool emitChange)174void FoldersModel::insertFileInfo(const QFileInfo& newFileInfo)
124{175{
125 QFileInfoList::iterator i;176 QFileInfoList::iterator i;
126 for (i = m_fileInfoList.begin(); i != m_fileInfoList.end(); ++i) {177 for (i = m_fileInfoList.begin(); i != m_fileInfoList.end(); ++i) {
127 QFileInfo fileInfo = *i;178 QFileInfo fileInfo = *i;
128 if (!moreRecentThan(newFileInfo, fileInfo)) {179 if (newerThan(newFileInfo, fileInfo)) {
129 if (emitChange) {180 int index = m_fileInfoList.indexOf(*i);
130 int index = m_fileInfoList.indexOf(*i);181 beginInsertRows(QModelIndex(), index, index);
131 beginInsertRows(QModelIndex(), index, index);182 m_fileInfoList.insert(i, newFileInfo);
132 m_fileInfoList.insert(i, newFileInfo);183 endInsertRows();
133 endInsertRows();
134 } else {
135 m_fileInfoList.insert(i, newFileInfo);
136 }
137 return;184 return;
138 }185 }
139 }186 }
140187
141 if (emitChange) {188 int index = m_fileInfoList.size();
142 int index = m_fileInfoList.size();189 beginInsertRows(QModelIndex(), index, index);
143 beginInsertRows(QModelIndex(), index, index);190 m_fileInfoList.append(newFileInfo);
144 m_fileInfoList.append(newFileInfo);191 endInsertRows();
145 endInsertRows();192 Q_EMIT countChanged();
146 Q_EMIT countChanged();
147 } else {
148 m_fileInfoList.append(newFileInfo);
149 }
150}193}
151194
152QHash<int, QByteArray> FoldersModel::roleNames() const195QHash<int, QByteArray> FoldersModel::roleNames() const
@@ -205,31 +248,6 @@
205 return data(index(row), roleNames().key(role.toUtf8()));248 return data(index(row), roleNames().key(role.toUtf8()));
206}249}
207250
208void FoldersModel::directoryChanged(const QString &directoryPath)
209{
210 /* Only react when a file is added. Ignore when a file was modified or
211 * deleted as this is taken care of by FoldersModel::fileChanged()
212 * To do so we go through all the files in directoryPath and add
213 * all the ones we were not watching before.
214 */
215 QStringList watchedFiles = m_watcher->files();
216 QDir directory(directoryPath);
217 QStringList files = directory.entryList(QDir::Files | QDir::Readable,
218 QDir::Time | QDir::Reversed);
219
220 Q_FOREACH (QString fileName, files) {
221 QString filePath = directory.absoluteFilePath(fileName);
222 if (!watchedFiles.contains(filePath)) {
223 QFileInfo fileInfo(filePath);
224 if (fileInfo.isDir()) continue;
225 m_watcher->addPath(filePath);
226 if (fileMatchesTypeFilters(fileInfo)) {
227 insertFileInfo(fileInfo, true);
228 }
229 }
230 }
231}
232
233void FoldersModel::fileChanged(const QString &filePath)251void FoldersModel::fileChanged(const QString &filePath)
234{252{
235 /* Act appropriately upon file change or removal */253 /* Act appropriately upon file change or removal */
@@ -242,7 +260,7 @@
242 if (fileIndex == -1) {260 if (fileIndex == -1) {
243 // file's type might have changed and file might have to be included261 // file's type might have changed and file might have to be included
244 if (fileMatchesTypeFilters(fileInfo)) {262 if (fileMatchesTypeFilters(fileInfo)) {
245 insertFileInfo(fileInfo, true);263 insertFileInfo(fileInfo);
246 }264 }
247 } else {265 } else {
248 // update file information266 // update file information
@@ -290,10 +308,44 @@
290 Q_EMIT selectedFilesChanged();308 Q_EMIT selectedFilesChanged();
291}309}
292310
311void FoldersModel::prependFile(QString filePath)
312{
313 if (!m_watcher->files().contains(filePath)) {
314 QFileInfo fileInfo(filePath);
315 m_watcher->addPath(filePath);
316 if (fileMatchesTypeFilters(fileInfo)) {
317 insertFileInfo(fileInfo);
318 }
319 }
320}
321
293void FoldersModel::selectAll()322void FoldersModel::selectAll()
294{323{
295 for (int row = 0; row < m_fileInfoList.size(); ++row) {324 for (int row = 0; row < m_fileInfoList.size(); ++row) {
296 if (!m_selectedFiles.contains(row))325 if (!m_selectedFiles.contains(row)) {
297 toggleSelected(row);326 m_selectedFiles.insert(row);
298 }327 }
328 Q_EMIT dataChanged(index(row), index(row));
329 }
330 Q_EMIT selectedFilesChanged();
331}
332
333void FoldersModel::deleteSelectedFiles()
334{
335 Q_FOREACH (int selectedFile, m_selectedFiles) {
336 QString filePath = m_fileInfoList.at(selectedFile).filePath();
337 QFile::remove(filePath);
338 }
339 m_selectedFiles.clear();
340 Q_EMIT selectedFilesChanged();
341}
342
343void FoldersModel::classBegin()
344{
345}
346
347void FoldersModel::componentComplete()
348{
349 m_completed = true;
350 updateFileInfoList();
299}351}
300352
=== modified file 'CameraApp/foldersmodel.h'
--- CameraApp/foldersmodel.h 2014-11-26 14:45:34 +0000
+++ CameraApp/foldersmodel.h 2015-01-24 18:49:40 +0000
@@ -23,8 +23,10 @@
23#include <QtCore/QFileSystemWatcher>23#include <QtCore/QFileSystemWatcher>
24#include <QtCore/QMimeDatabase>24#include <QtCore/QMimeDatabase>
25#include <QtCore/QSet>25#include <QtCore/QSet>
26#include <QtCore/QFutureWatcher>
27#include <QtQml/QQmlParserStatus>
2628
27class FoldersModel : public QAbstractListModel29class FoldersModel : public QAbstractListModel, public QQmlParserStatus
28{30{
29 Q_OBJECT31 Q_OBJECT
30 Q_PROPERTY (QStringList folders READ folders WRITE setFolders NOTIFY foldersChanged)32 Q_PROPERTY (QStringList folders READ folders WRITE setFolders NOTIFY foldersChanged)
@@ -32,6 +34,7 @@
32 Q_PROPERTY (QList<int> selectedFiles READ selectedFiles NOTIFY selectedFilesChanged)34 Q_PROPERTY (QList<int> selectedFiles READ selectedFiles NOTIFY selectedFilesChanged)
33 Q_PROPERTY (bool singleSelectionOnly READ singleSelectionOnly WRITE setSingleSelectionOnly NOTIFY singleSelectionOnlyChanged)35 Q_PROPERTY (bool singleSelectionOnly READ singleSelectionOnly WRITE setSingleSelectionOnly NOTIFY singleSelectionOnlyChanged)
34 Q_PROPERTY(int count READ count NOTIFY countChanged)36 Q_PROPERTY(int count READ count NOTIFY countChanged)
37 Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged)
3538
36public:39public:
37 enum Roles {40 enum Roles {
@@ -52,10 +55,13 @@
52 bool singleSelectionOnly() const;55 bool singleSelectionOnly() const;
53 void setSingleSelectionOnly(bool singleSelectionOnly);56 void setSingleSelectionOnly(bool singleSelectionOnly);
54 int count() const;57 int count() const;
58 bool loading() const;
5559
56 void updateFileInfoList();60 void updateFileInfoList();
61 QPair<QFileInfoList, QStringList> computeFileInfoList(QStringList folders);
57 bool fileMatchesTypeFilters(const QFileInfo& newFileInfo);62 bool fileMatchesTypeFilters(const QFileInfo& newFileInfo);
58 void insertFileInfo(const QFileInfo& newFileInfo, bool emitChange);63 void insertFileInfo(const QFileInfo& newFileInfo);
64 void setFileInfoList(const QFileInfoList& fileInfoList, const QStringList& filesToWatch);
5965
60 QHash<int, QByteArray> roleNames() const;66 QHash<int, QByteArray> roleNames() const;
61 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;67 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
@@ -64,10 +70,16 @@
64 Q_INVOKABLE void toggleSelected(int row);70 Q_INVOKABLE void toggleSelected(int row);
65 Q_INVOKABLE void clearSelection();71 Q_INVOKABLE void clearSelection();
66 Q_INVOKABLE void selectAll();72 Q_INVOKABLE void selectAll();
73 Q_INVOKABLE void prependFile(QString filePath);
74 Q_INVOKABLE void deleteSelectedFiles();
75
76 // inherited from QQmlParserStatus
77 void classBegin();
78 void componentComplete();
6779
68public Q_SLOTS:80public Q_SLOTS:
69 void directoryChanged(const QString &directoryPath);
70 void fileChanged(const QString &directoryPath);81 void fileChanged(const QString &directoryPath);
82 void updateFileInfoListFinished();
7183
72Q_SIGNALS:84Q_SIGNALS:
73 void foldersChanged();85 void foldersChanged();
@@ -75,6 +87,7 @@
75 void selectedFilesChanged();87 void selectedFilesChanged();
76 void singleSelectionOnlyChanged();88 void singleSelectionOnlyChanged();
77 void countChanged();89 void countChanged();
90 void loadingChanged();
7891
79private:92private:
80 QStringList m_folders;93 QStringList m_folders;
@@ -84,6 +97,9 @@
84 QMimeDatabase m_mimeDatabase;97 QMimeDatabase m_mimeDatabase;
85 QSet<int> m_selectedFiles;98 QSet<int> m_selectedFiles;
86 bool m_singleSelectionOnly;99 bool m_singleSelectionOnly;
100 QFutureWatcher<QPair<QFileInfoList, QStringList> > m_updateFutureWatcher;
101 bool m_completed;
102 bool m_loading;
87};103};
88104
89#endif // FOLDERSMODEL_H105#endif // FOLDERSMODEL_H
90106
=== modified file 'GalleryView.qml'
--- GalleryView.qml 2014-12-05 18:50:53 +0000
+++ GalleryView.qml 2015-01-24 18:49:40 +0000
@@ -47,6 +47,10 @@
47 showLastPhotoTakenPending = true;47 showLastPhotoTakenPending = true;
48 }48 }
4949
50 function prependMediaToModel(filePath) {
51 galleryView.model.prependFile(filePath);
52 }
53
50 function exitUserSelectionMode() {54 function exitUserSelectionMode() {
51 if (gridMode) {55 if (gridMode) {
52 model.clearSelection();56 model.clearSelection();
@@ -155,7 +159,7 @@
155 Rectangle {159 Rectangle {
156 objectName: "noMediaHint"160 objectName: "noMediaHint"
157 anchors.fill: parent161 anchors.fill: parent
158 visible: model.count === 0162 visible: model.count === 0 && !model.loading
159 color: "#0F0F0F"163 color: "#0F0F0F"
160164
161 Icon {165 Icon {
@@ -186,6 +190,40 @@
186 }190 }
187 }191 }
188192
193 Rectangle {
194 objectName: "scanningMediaHint"
195 anchors.fill: parent
196 visible: model.loading
197 color: "#0F0F0F"
198
199 Icon {
200 id: scanningMediaIcon
201 anchors {
202 horizontalCenter: parent.horizontalCenter
203 verticalCenter: parent.verticalCenter
204 verticalCenterOffset: -units.gu(1)
205 }
206 height: units.gu(9)
207 width: units.gu(9)
208 color: "white"
209 opacity: 0.2
210 name: "camera-app-symbolic"
211 }
212
213 Label {
214 id: scanningMediaLabel
215 anchors {
216 horizontalCenter: parent.horizontalCenter
217 top: scanningMediaIcon.bottom
218 topMargin: units.gu(4)
219 }
220 text: i18n.tr("Scanning for content...")
221 color: "white"
222 opacity: 0.2
223 fontSize: "large"
224 }
225 }
226
189 state: galleryView.gridMode || main.contentExportMode ? "GRID" : "SLIDESHOW"227 state: galleryView.gridMode || main.contentExportMode ? "GRID" : "SLIDESHOW"
190 states: [228 states: [
191 State {229 State {
192230
=== modified file 'GalleryViewLoader.qml'
--- GalleryViewLoader.qml 2014-08-27 00:31:30 +0000
+++ GalleryViewLoader.qml 2015-01-24 18:49:40 +0000
@@ -27,6 +27,11 @@
27 loader.item.showLastPhotoTaken();27 loader.item.showLastPhotoTaken();
28 }28 }
2929
30 function prependMediaToModel(filePath) {
31 loader.item.prependMediaToModel(filePath);
32 }
33
34
30 asynchronous: true35 asynchronous: true
3136
32 Component.onCompleted: {37 Component.onCompleted: {
3338
=== modified file 'PhotogridView.qml'
--- PhotogridView.qml 2014-12-03 12:37:15 +0000
+++ PhotogridView.qml 2015-01-24 18:49:40 +0000
@@ -210,12 +210,7 @@
210 }210 }
211211
212 onDeleteFiles: {212 onDeleteFiles: {
213 for (var i=model.selectedFiles.length-1; i>=0; i--) {213 model.deleteSelectedFiles();
214 var currentFilePath = model.get(model.selectedFiles[i], "filePath");
215 model.toggleSelected(model.selectedFiles[i])
216 fileOperations.remove(currentFilePath);
217 }
218
219 photogridView.exitUserSelectionMode();214 photogridView.exitUserSelectionMode();
220 }215 }
221 }216 }
222217
=== modified file 'SlideshowView.qml'
--- SlideshowView.qml 2014-12-05 18:50:53 +0000
+++ SlideshowView.qml 2015-01-24 18:49:40 +0000
@@ -79,6 +79,12 @@
79 // were hitting https://bugreports.qt-project.org/browse/QTBUG-4103579 // were hitting https://bugreports.qt-project.org/browse/QTBUG-41035
80 highlightMoveDuration: 080 highlightMoveDuration: 0
81 snapMode: ListView.SnapOneItem81 snapMode: ListView.SnapOneItem
82 onCountChanged: {
83 // currentIndex is -1 by default and stays so until manually set to something else
84 if (currentIndex == -1 && count != 0) {
85 currentIndex = 0;
86 }
87 }
82 spacing: units.gu(1)88 spacing: units.gu(1)
83 interactive: currentItem ? !currentItem.pinchInProgress : true89 interactive: currentItem ? !currentItem.pinchInProgress : true
84 property real maxDimension: Math.max(width, height)90 property real maxDimension: Math.max(width, height)
8591
=== modified file 'ViewFinderView.qml'
--- ViewFinderView.qml 2014-12-11 12:24:25 +0000
+++ ViewFinderView.qml 2015-01-24 18:49:40 +0000
@@ -29,8 +29,8 @@
29 property bool touchAcquired: viewFinderOverlay.touchAcquired || camera.videoRecorder.recorderState == CameraRecorder.RecordingState29 property bool touchAcquired: viewFinderOverlay.touchAcquired || camera.videoRecorder.recorderState == CameraRecorder.RecordingState
30 property bool inView30 property bool inView
31 property alias captureMode: camera.captureMode31 property alias captureMode: camera.captureMode
32 signal photoTaken32 signal photoTaken(string filePath)
33 signal videoShot33 signal videoShot(string filePath)
3434
35 Camera {35 Camera {
36 id: camera36 id: camera
@@ -84,18 +84,19 @@
84 }84 }
85 onImageCaptured: {85 onImageCaptured: {
86 snapshot.source = preview;86 snapshot.source = preview;
87 if (!main.contentExportMode) {
88 viewFinderOverlay.visible = true;
89 snapshot.startOutAnimation();
90 if (photoRollHint.necessary) {
91 photoRollHint.enable();
92 }
93 }
87 }94 }
88 onImageSaved: {95 onImageSaved: {
89 if (main.contentExportMode) {96 if (main.contentExportMode) {
90 viewFinderExportConfirmation.confirmExport(path);97 viewFinderExportConfirmation.confirmExport(path);
91 } else {
92 viewFinderOverlay.visible = true;
93 snapshot.startOutAnimation();
94 if (photoRollHint.necessary) {
95 photoRollHint.enable();
96 }
97 }98 }
98 viewFinderView.photoTaken();99 viewFinderView.photoTaken(path);
99 metricPhotos.increment();100 metricPhotos.increment();
100 console.log("Picture saved as " + path);101 console.log("Picture saved as " + path);
101 }102 }
@@ -109,7 +110,7 @@
109 }110 }
110 metricVideos.increment()111 metricVideos.increment()
111 viewFinderOverlay.visible = true;112 viewFinderOverlay.visible = true;
112 viewFinderView.videoShot();113 viewFinderView.videoShot(videoRecorder.actualLocation);
113 }114 }
114 }115 }
115 }116 }
116117
=== modified file 'camera-app.qml'
--- camera-app.qml 2014-09-05 11:43:11 +0000
+++ camera-app.qml 2015-01-24 18:49:40 +0000
@@ -152,8 +152,14 @@
152 height: viewSwitcher.height152 height: viewSwitcher.height
153 overlayVisible: !viewSwitcher.moving && !viewSwitcher.flicking153 overlayVisible: !viewSwitcher.moving && !viewSwitcher.flicking
154 inView: !viewSwitcher.atXEnd154 inView: !viewSwitcher.atXEnd
155 onPhotoTaken: galleryView.showLastPhotoTaken();155 onPhotoTaken: {
156 onVideoShot: galleryView.showLastPhotoTaken();156 galleryView.prependMediaToModel(filePath);
157 galleryView.showLastPhotoTaken();
158 }
159 onVideoShot: {
160 galleryView.prependMediaToModel(filePath);
161 galleryView.showLastPhotoTaken();
162 }
157 }163 }
158164
159 GalleryViewLoader {165 GalleryViewLoader {
160166
=== modified file 'po/camera-app.pot'
--- po/camera-app.pot 2014-12-15 10:51:14 +0000
+++ po/camera-app.pot 2015-01-24 18:49:40 +0000
@@ -8,7 +8,7 @@
8msgstr ""8msgstr ""
9"Project-Id-Version: camera-app\n"9"Project-Id-Version: camera-app\n"
10"Report-Msgid-Bugs-To: \n"10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2014-12-15 08:50-0200\n"11"POT-Creation-Date: 2015-01-24 15:51-0200\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -29,10 +29,14 @@
29msgid "Cancel"29msgid "Cancel"
30msgstr ""30msgstr ""
3131
32#: ../GalleryView.qml:18232#: ../GalleryView.qml:186
33msgid "No media available."33msgid "No media available."
34msgstr ""34msgstr ""
3535
36#: ../GalleryView.qml:220
37msgid "Scanning for content..."
38msgstr ""
39
36#: ../GalleryViewHeader.qml:7540#: ../GalleryViewHeader.qml:75
37msgid "Select"41msgid "Select"
38msgstr ""42msgstr ""
@@ -49,55 +53,55 @@
49msgid "Share"53msgid "Share"
50msgstr ""54msgstr ""
5155
52#: ../ViewFinderOverlay.qml:185 ../ViewFinderOverlay.qml:20856#: ../ViewFinderOverlay.qml:195 ../ViewFinderOverlay.qml:218
53#: ../ViewFinderOverlay.qml:236 ../ViewFinderOverlay.qml:25957#: ../ViewFinderOverlay.qml:246 ../ViewFinderOverlay.qml:269
54#: ../ViewFinderOverlay.qml:33658#: ../ViewFinderOverlay.qml:346
55msgid "On"59msgid "On"
56msgstr ""60msgstr ""
5761
58#: ../ViewFinderOverlay.qml:190 ../ViewFinderOverlay.qml:21862#: ../ViewFinderOverlay.qml:200 ../ViewFinderOverlay.qml:228
59#: ../ViewFinderOverlay.qml:241 ../ViewFinderOverlay.qml:26463#: ../ViewFinderOverlay.qml:251 ../ViewFinderOverlay.qml:274
60#: ../ViewFinderOverlay.qml:283 ../ViewFinderOverlay.qml:34164#: ../ViewFinderOverlay.qml:293 ../ViewFinderOverlay.qml:351
61msgid "Off"65msgid "Off"
62msgstr ""66msgstr ""
6367
64#: ../ViewFinderOverlay.qml:21368#: ../ViewFinderOverlay.qml:223
65msgid "Auto"69msgid "Auto"
66msgstr ""70msgstr ""
6771
68#: ../ViewFinderOverlay.qml:25072#: ../ViewFinderOverlay.qml:260
69msgid "HDR"73msgid "HDR"
70msgstr ""74msgstr ""
7175
72#: ../ViewFinderOverlay.qml:28876#: ../ViewFinderOverlay.qml:298
73msgid "5 seconds"77msgid "5 seconds"
74msgstr ""78msgstr ""
7579
76#: ../ViewFinderOverlay.qml:29380#: ../ViewFinderOverlay.qml:303
77msgid "15 seconds"81msgid "15 seconds"
78msgstr ""82msgstr ""
7983
80#: ../ViewFinderOverlay.qml:31084#: ../ViewFinderOverlay.qml:320
81msgid "Fine Quality"85msgid "Fine Quality"
82msgstr ""86msgstr ""
8387
84#: ../ViewFinderOverlay.qml:31488#: ../ViewFinderOverlay.qml:324
85msgid "Normal Quality"89msgid "Normal Quality"
86msgstr ""90msgstr ""
8791
88#: ../ViewFinderOverlay.qml:31892#: ../ViewFinderOverlay.qml:328
89msgid "Basic Quality"93msgid "Basic Quality"
90msgstr ""94msgstr ""
9195
92#: ../ViewFinderOverlay.qml:35096#: ../ViewFinderOverlay.qml:360
93msgid "SD"97msgid "SD"
94msgstr ""98msgstr ""
9599
96#: ../ViewFinderOverlay.qml:358100#: ../ViewFinderOverlay.qml:368
97msgid "Save to SD Card"101msgid "Save to SD Card"
98msgstr ""102msgstr ""
99103
100#: ../ViewFinderOverlay.qml:363104#: ../ViewFinderOverlay.qml:373
101msgid "Save internally"105msgid "Save internally"
102msgstr ""106msgstr ""
103107
@@ -141,21 +145,21 @@
141msgid "Lighting Condition;Day;Cloudy;Inside"145msgid "Lighting Condition;Day;Cloudy;Inside"
142msgstr ""146msgstr ""
143147
144#: ../camera-app.qml:214148#: ../camera-app.qml:220
145#, qt-format149#, qt-format
146msgid "<b>%1</b> photos taken today"150msgid "<b>%1</b> photos taken today"
147msgstr ""151msgstr ""
148152
149#: ../camera-app.qml:215153#: ../camera-app.qml:221
150msgid "No photos taken today"154msgid "No photos taken today"
151msgstr ""155msgstr ""
152156
153#: ../camera-app.qml:223157#: ../camera-app.qml:229
154#, qt-format158#, qt-format
155msgid "<b>%1</b> videos recorded today"159msgid "<b>%1</b> videos recorded today"
156msgstr ""160msgstr ""
157161
158#: ../camera-app.qml:224162#: ../camera-app.qml:230
159msgid "No videos recorded today"163msgid "No videos recorded today"
160msgstr ""164msgstr ""
161165
162166
=== modified file 'tests/autopilot/camera_app/tests/test_gallery_view.py'
--- tests/autopilot/camera_app/tests/test_gallery_view.py 2014-11-20 22:02:12 +0000
+++ tests/autopilot/camera_app/tests/test_gallery_view.py 2015-01-24 18:49:40 +0000
@@ -62,10 +62,11 @@
62 os.remove(os.path.join(self.videos_dir, f))62 os.remove(os.path.join(self.videos_dir, f))
6363
64 def add_sample_photo(self):64 def add_sample_photo(self):
65 # add a fake photo to pictures_dir65 self.main_window.swipe_to_viewfinder(self)
66 photo_path = os.path.join(self.pictures_dir, "fake_photo.jpg")66 exposure_button = self.main_window.get_exposure_button()
67 with open(photo_path, 'a'):67 self.assertThat(exposure_button.enabled, Eventually(Equals(True)))
68 os.utime(photo_path, None)68 self.pointing_device.move_to_object(exposure_button)
69 self.pointing_device.click()
6970
70 def select_first_photo(self):71 def select_first_photo(self):
71 # select the first photo72 # select the first photo

Subscribers

People subscribed via source and target branches