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

Proposed by Florian Boucault
Status: Merged
Approved by: Bill Filler
Approved revision: 436
Merged at revision: 451
Proposed branch: lp:~fboucault/camera-app/sdcard
Merge into: lp:camera-app
Diff against target: 285 lines (+136/-17)
6 files modified
GalleryView.qml (+3/-1)
ViewFinderOverlay.qml (+36/-0)
camera-apparmor.json (+1/-1)
cameraapplication.cpp (+58/-0)
cameraapplication.h (+11/-0)
po/camera-app.pot (+27/-15)
To merge this branch: bzr merge lp:~fboucault/camera-app/sdcard
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Ubuntu Phablet Team Pending
Review via email: mp+241971@code.launchpad.net

Commit message

Add an option to save photos and videos to external SD card.
Adapted bottom edge UI to accomodate for more than 3 settings.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~fboucault/camera-app/sdcard updated
427. By Florian Boucault

Blurred viewfinder is now darker making bottom edge more readable.

428. By Florian Boucault

Less opaque blur.

429. By Florian Boucault

Merged trunk

430. By Florian Boucault

Show/hide SD card option when an SD card is present/not present.

431. By Florian Boucault

Update pot

432. By Florian Boucault

Better backend code.

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)
Revision history for this message
Florian Boucault (fboucault) wrote :

Pending two security fixes:
1) https://bugs.launchpad.net/ubuntu/+source/apparmor-easyprof-ubuntu/+bug/1391930
2) creation of Pictures and Videos directories on the SD card when plugged in (sergiusens taking care of it)

Revision history for this message
Florian Boucault (fboucault) wrote :

> 2) creation of Pictures and Videos directories on the SD card when plugged in
> (sergiusens taking care of it)

Link: https://code.launchpad.net/~sergiusens/ciborium/mediadirs/+merge/242838

lp:~fboucault/camera-app/sdcard updated
433. By Florian Boucault

Removed unwanted write/read paths from apparmor profile.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~fboucault/camera-app/sdcard updated
434. By Florian Boucault

Merged from trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~fboucault/camera-app/sdcard updated
435. By Florian Boucault

Merged from trunk

436. By Florian Boucault

Added bug

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 'GalleryView.qml'
--- GalleryView.qml 2014-12-03 12:37:15 +0000
+++ GalleryView.qml 2014-12-11 16:55:23 +0000
@@ -29,7 +29,9 @@
29 property bool userSelectionMode: false29 property bool userSelectionMode: false
30 property Item currentView: state == "GRID" ? photogridView : slideshowView30 property Item currentView: state == "GRID" ? photogridView : slideshowView
31 property var model: FoldersModel {31 property var model: FoldersModel {
32 folders: [application.picturesLocation, application.videosLocation]32 folders: [application.picturesLocation, application.videosLocation,
33 application.removableStoragePicturesLocation,
34 application.removableStorageVideosLocation]
33 typeFilters: !main.contentExportMode ? [ "image", "video" ]35 typeFilters: !main.contentExportMode ? [ "image", "video" ]
34 : [MimeTypeMapper.contentTypeToMimeType(main.transferContentType)]36 : [MimeTypeMapper.contentTypeToMimeType(main.transferContentType)]
35 singleSelectionOnly: main.transfer.selectionType === ContentTransfer.Single37 singleSelectionOnly: main.transfer.selectionType === ContentTransfer.Single
3638
=== modified file 'ViewFinderOverlay.qml'
--- ViewFinderOverlay.qml 2014-12-09 21:48:11 +0000
+++ ViewFinderOverlay.qml 2014-12-11 16:55:23 +0000
@@ -46,6 +46,7 @@
46 property int selfTimerDelay: 046 property int selfTimerDelay: 0
47 property int encodingQuality: 2 // QMultimedia.NormalQuality47 property int encodingQuality: 2 // QMultimedia.NormalQuality
48 property bool gridEnabled: false48 property bool gridEnabled: false
49 property bool preferRemovableStorage: false
49 }50 }
5051
51 Binding {52 Binding {
@@ -296,9 +297,39 @@
296 label: QT_TR_NOOP("Off")297 label: QT_TR_NOOP("Off")
297 value: false298 value: false
298 }299 }
300 },
301 ListModel {
302 id: removableStorageOptionsModel
303
304 property string settingsProperty: "preferRemovableStorage"
305 property string icon: ""
306 property string label: i18n.tr("SD")
307 property bool isToggle: true
308 property int selectedIndex: bottomEdge.indexForValue(removableStorageOptionsModel, settings.preferRemovableStorage)
309 property bool available: application.removableStoragePresent
310 property bool visible: available
311
312 ListElement {
313 icon: ""
314 label: QT_TR_NOOP("Save to SD Card")
315 value: true
316 }
317 ListElement {
318 icon: ""
319 label: QT_TR_NOOP("Save internally")
320 value: false
321 }
299 }322 }
300 ]323 ]
301324
325 /* FIXME: application.removableStoragePresent is not updated dynamically.
326 Workaround that by reading it when the bottom edge is opened/closed.
327 */
328 Connections {
329 target: bottomEdge
330 onOpenedChanged: removableStorageOptionsModel.available = application.removableStoragePresent
331 }
332
302 function indexForValue(model, value) {333 function indexForValue(model, value) {
303 var i;334 var i;
304 var element;335 var element;
@@ -418,6 +449,9 @@
418 }449 }
419450
420 if (camera.captureMode == Camera.CaptureVideo) {451 if (camera.captureMode == Camera.CaptureVideo) {
452 if (application.removableStoragePresent && settings.preferRemovableStorage) {
453 camera.videoRecorder.outputLocation = application.removableStorageVideosLocation;
454 }
421 if (camera.videoRecorder.recorderState == CameraRecorder.StoppedState) {455 if (camera.videoRecorder.recorderState == CameraRecorder.StoppedState) {
422 camera.videoRecorder.setMetadata("Orientation", orientation);456 camera.videoRecorder.setMetadata("Orientation", orientation);
423 camera.videoRecorder.record();457 camera.videoRecorder.record();
@@ -441,6 +475,8 @@
441 }475 }
442 if (main.contentExportMode) {476 if (main.contentExportMode) {
443 camera.imageCapture.captureToLocation(application.temporaryLocation);477 camera.imageCapture.captureToLocation(application.temporaryLocation);
478 } else if (application.removableStoragePresent && settings.preferRemovableStorage) {
479 camera.imageCapture.captureToLocation(application.removableStoragePicturesLocation);
444 } else {480 } else {
445 camera.imageCapture.captureToLocation(application.picturesLocation);481 camera.imageCapture.captureToLocation(application.picturesLocation);
446 }482 }
447483
=== modified file 'camera-apparmor.json'
--- camera-apparmor.json 2014-07-31 18:41:17 +0000
+++ camera-apparmor.json 2014-12-11 16:55:23 +0000
@@ -11,4 +11,4 @@
11 "location"11 "location"
12 ],12 ],
13 "policy_version": 1.213 "policy_version": 1.2
14}
15\ No newline at end of file14\ No newline at end of file
15}
1616
=== modified file 'cameraapplication.cpp'
--- cameraapplication.cpp 2014-09-03 18:51:53 +0000
+++ cameraapplication.cpp 2014-12-11 16:55:23 +0000
@@ -147,3 +147,61 @@
147 dir.mkpath(location);147 dir.mkpath(location);
148 return location;148 return location;
149}149}
150
151bool CameraApplication::removableStoragePresent() const
152{
153 return !removableStorageLocation().isEmpty();
154}
155
156QString CameraApplication::removableStorageLocation() const
157{
158 /* FIXME: when Qt5.4 is available, switch to using newly introduced
159 * QStorageInfo API.
160 * Ref.: http://doc-snapshot.qt-project.org/qt5-5.4/qstorageinfo.html
161 */
162 QString userName = qgetenv("USER");
163 QDir media("/media/" + userName);
164 QStringList mediaDirs = media.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
165
166 if (mediaDirs.size() > 0) {
167 return QString("/media/" + userName + "/" + mediaDirs.at(0));
168 } else {
169 return QString();
170 }
171}
172
173QString CameraApplication::removableStoragePicturesLocation() const
174{
175 QString storageLocation = removableStorageLocation();
176 if (storageLocation.isEmpty()) {
177 return QString();
178 }
179
180 QStringList locations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
181 QString pictureDir = QString(locations.at(0)).split("/").value(3);
182 if (pictureDir.isEmpty()){
183 return QString();
184 }
185 QString location = storageLocation + "/" + pictureDir;
186 QDir dir;
187 dir.mkpath(location);
188 return location;
189}
190
191QString CameraApplication::removableStorageVideosLocation() const
192{
193 QString storageLocation = removableStorageLocation();
194 if (storageLocation.isEmpty()) {
195 return QString();
196 }
197
198 QStringList locations = QStandardPaths::standardLocations(QStandardPaths::MoviesLocation);
199 QString movieDir = QString(locations.at(0)).split("/").value(3);
200 if (movieDir.isEmpty()){
201 return QString();
202 }
203 QString location = storageLocation + "/" + movieDir;
204 QDir dir;
205 dir.mkpath(location);
206 return location;
207}
150208
=== modified file 'cameraapplication.h'
--- cameraapplication.h 2014-07-31 18:41:17 +0000
+++ cameraapplication.h 2014-12-11 16:55:23 +0000
@@ -32,6 +32,10 @@
32 Q_PROPERTY(QString picturesLocation READ picturesLocation CONSTANT)32 Q_PROPERTY(QString picturesLocation READ picturesLocation CONSTANT)
33 Q_PROPERTY(QString videosLocation READ videosLocation CONSTANT)33 Q_PROPERTY(QString videosLocation READ videosLocation CONSTANT)
34 Q_PROPERTY(QString temporaryLocation READ temporaryLocation CONSTANT)34 Q_PROPERTY(QString temporaryLocation READ temporaryLocation CONSTANT)
35 Q_PROPERTY(bool removableStoragePresent READ removableStoragePresent NOTIFY removableStoragePresentChanged)
36 Q_PROPERTY(QString removableStorageLocation READ removableStorageLocation CONSTANT)
37 Q_PROPERTY(QString removableStoragePicturesLocation READ removableStoragePicturesLocation CONSTANT)
38 Q_PROPERTY(QString removableStorageVideosLocation READ removableStorageVideosLocation CONSTANT)
3539
36public:40public:
37 CameraApplication(int &argc, char **argv);41 CameraApplication(int &argc, char **argv);
@@ -41,6 +45,13 @@
41 QString picturesLocation() const;45 QString picturesLocation() const;
42 QString videosLocation() const;46 QString videosLocation() const;
43 QString temporaryLocation() const;47 QString temporaryLocation() const;
48 bool removableStoragePresent() const;
49 QString removableStorageLocation() const;
50 QString removableStoragePicturesLocation() const;
51 QString removableStorageVideosLocation() const;
52
53Q_SIGNALS:
54 void removableStoragePresentChanged();
4455
45private:56private:
46 QScopedPointer<QQuickView> m_view;57 QScopedPointer<QQuickView> m_view;
4758
=== modified file 'po/camera-app.pot'
--- po/camera-app.pot 2014-12-08 11:49:38 +0000
+++ po/camera-app.pot 2014-12-11 16:55:23 +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-08 09:47-0200\n"11"POT-Creation-Date: 2014-12-11 10:23-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,7 +29,7 @@
29msgid "Cancel"29msgid "Cancel"
30msgstr ""30msgstr ""
3131
32#: ../GalleryView.qml:18032#: ../GalleryView.qml:182
33msgid "No media available."33msgid "No media available."
34msgstr ""34msgstr ""
3535
@@ -49,46 +49,58 @@
49msgid "Share"49msgid "Share"
50msgstr ""50msgstr ""
5151
52#: ../ViewFinderOverlay.qml:140 ../ViewFinderOverlay.qml:16352#: ../ViewFinderOverlay.qml:141 ../ViewFinderOverlay.qml:164
53#: ../ViewFinderOverlay.qml:191 ../ViewFinderOverlay.qml:21453#: ../ViewFinderOverlay.qml:192 ../ViewFinderOverlay.qml:215
54#: ../ViewFinderOverlay.qml:29154#: ../ViewFinderOverlay.qml:292
55msgid "On"55msgid "On"
56msgstr ""56msgstr ""
5757
58#: ../ViewFinderOverlay.qml:145 ../ViewFinderOverlay.qml:17358#: ../ViewFinderOverlay.qml:146 ../ViewFinderOverlay.qml:174
59#: ../ViewFinderOverlay.qml:196 ../ViewFinderOverlay.qml:21959#: ../ViewFinderOverlay.qml:197 ../ViewFinderOverlay.qml:220
60#: ../ViewFinderOverlay.qml:238 ../ViewFinderOverlay.qml:29660#: ../ViewFinderOverlay.qml:239 ../ViewFinderOverlay.qml:297
61msgid "Off"61msgid "Off"
62msgstr ""62msgstr ""
6363
64#: ../ViewFinderOverlay.qml:16864#: ../ViewFinderOverlay.qml:169
65msgid "Auto"65msgid "Auto"
66msgstr ""66msgstr ""
6767
68#: ../ViewFinderOverlay.qml:20568#: ../ViewFinderOverlay.qml:206
69msgid "HDR"69msgid "HDR"
70msgstr ""70msgstr ""
7171
72#: ../ViewFinderOverlay.qml:24372#: ../ViewFinderOverlay.qml:244
73msgid "5 seconds"73msgid "5 seconds"
74msgstr ""74msgstr ""
7575
76#: ../ViewFinderOverlay.qml:24876#: ../ViewFinderOverlay.qml:249
77msgid "15 seconds"77msgid "15 seconds"
78msgstr ""78msgstr ""
7979
80#: ../ViewFinderOverlay.qml:26580#: ../ViewFinderOverlay.qml:266
81msgid "Fine Quality"81msgid "Fine Quality"
82msgstr ""82msgstr ""
8383
84#: ../ViewFinderOverlay.qml:26984#: ../ViewFinderOverlay.qml:270
85msgid "Normal Quality"85msgid "Normal Quality"
86msgstr ""86msgstr ""
8787
88#: ../ViewFinderOverlay.qml:27388#: ../ViewFinderOverlay.qml:274
89msgid "Basic Quality"89msgid "Basic Quality"
90msgstr ""90msgstr ""
9191
92#: ../ViewFinderOverlay.qml:306
93msgid "SD"
94msgstr ""
95
96#: ../ViewFinderOverlay.qml:314
97msgid "Save to SD Card"
98msgstr ""
99
100#: ../ViewFinderOverlay.qml:319
101msgid "Save internally"
102msgstr ""
103
92#: ../camera-app.qml:36104#: ../camera-app.qml:36
93msgid "Flash"105msgid "Flash"
94msgstr ""106msgstr ""

Subscribers

People subscribed via source and target branches