[Merge] lp:~fboucault/camera-app/content_source into lp:camera-app
Ugo Riboni
ugo.riboni at canonical.com
Mon Aug 4 11:32:18 UTC 2014
Review: Needs Fixing
Minor style and edge cases pointed out inline.
Runs fine, but not sure how to test the actual functionality.
Diff comments:
> === modified file 'CMakeLists.txt'
> --- CMakeLists.txt 2014-07-29 10:06:21 +0000
> +++ CMakeLists.txt 2014-08-01 15:50:37 +0000
> @@ -120,6 +120,8 @@
> DESTINATION ${CMAKE_INSTALL_PREFIX})
> install(FILES camera-apparmor.json
> DESTINATION ${CMAKE_INSTALL_PREFIX})
> + install(FILES camera-contenthub.json
> + DESTINATION ${CMAKE_INSTALL_PREFIX})
>
> else(CLICK_MODE)
> install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE}
>
> === modified file 'CameraApp/foldersmodel.cpp'
> --- CameraApp/foldersmodel.cpp 2014-07-29 11:57:12 +0000
> +++ CameraApp/foldersmodel.cpp 2014-08-01 15:50:37 +0000
> @@ -20,7 +20,8 @@
> #include <QtCore/QDateTime>
>
> FoldersModel::FoldersModel(QObject *parent) :
> - QAbstractListModel(parent)
> + QAbstractListModel(parent),
> + m_singleSelectionOnly(true)
> {
> m_watcher = new QFileSystemWatcher(this);
> connect(m_watcher, SIGNAL(directoryChanged(QString)), this, SLOT(directoryChanged(QString)));
> @@ -40,31 +41,60 @@
> Q_EMIT foldersChanged();
> }
>
> -QStringList FoldersModel::nameFilters() const
> +QStringList FoldersModel::typeFilters() const
> {
> - return m_nameFilters;
> + return m_typeFilters;
> }
>
> -void FoldersModel::setNameFilters(const QStringList& nameFilters)
> +void FoldersModel::setTypeFilters(const QStringList& typeFilters)
> {
> - m_nameFilters = nameFilters;
> + m_typeFilters = typeFilters;
> updateFileInfoList();
> - Q_EMIT nameFiltersChanged();
> -}
> + Q_EMIT typeFiltersChanged();
> +}
> +
> +QList<int> FoldersModel::selectedFiles() const
> +{
> + return m_selectedFiles.values();
> +}
> +
> +bool FoldersModel::singleSelectionOnly() const
> +{
> + return m_singleSelectionOnly;
> +}
> +
> +void FoldersModel::setSingleSelectionOnly(bool singleSelectionOnly)
> +{
> + if (singleSelectionOnly != m_singleSelectionOnly) {
> + if (singleSelectionOnly && m_selectedFiles.count() > 1) {
> + clearSelection();
> + }
> + m_singleSelectionOnly = singleSelectionOnly;
> + Q_EMIT singleSelectionOnlyChanged();
> + }
> +}
> +
>
> void FoldersModel::updateFileInfoList()
> {
> m_fileInfoList.clear();
> Q_FOREACH (QString folder, m_folders) {
> QDir currentDir(folder);
> - QFileInfoList fileInfoList = currentDir.entryInfoList(m_nameFilters,
> - QDir::Files | QDir::Readable,
> + QFileInfoList fileInfoList = currentDir.entryInfoList(QDir::Files | QDir::Readable,
> QDir::Time | QDir::Reversed);
> Q_FOREACH (QFileInfo fileInfo, fileInfoList) {
> - insertFileInfo(fileInfo);
> + QString type = m_mimeDatabase.mimeTypeForFile(fileInfo).name();
> + Q_FOREACH (QString filterType, m_typeFilters) {
> + if (type.startsWith(filterType)) {
> + insertFileInfo(fileInfo);
> + break;
> + }
> + }
> }
> }
> endResetModel();
> + m_selectedFiles.clear();
> + Q_EMIT selectedFilesChanged();
> }
>
> bool moreRecentThan(const QFileInfo& fileInfo1, const QFileInfo& fileInfo2)
> @@ -94,6 +124,7 @@
> roles[FilePathRole] = "filePath";
> roles[FileUrlRole] = "fileURL";
> roles[FileTypeRole] = "fileType";
> + roles[SelectedRole] = "selected";
> return roles;
> }
>
> @@ -120,7 +151,10 @@
> return QUrl::fromLocalFile(item.filePath());
> break;
> case FileTypeRole:
> - return m_mimeDatabase.mimeTypeForFile(item.fileName()).name();
> + return m_mimeDatabase.mimeTypeForFile(item).name();
> + break;
> + case SelectedRole:
> + return m_selectedFiles.contains(index.row());
> break;
> default:
> break;
> @@ -143,3 +177,31 @@
> {
> updateFileInfoList();
> }
> +
> +void FoldersModel::toggleSelected(int row)
> +{
> + if (m_selectedFiles.contains(row)) {
> + m_selectedFiles.remove(row);
> + } else {
> + if (m_singleSelectionOnly) {
> + int previouslySelected = m_selectedFiles.isEmpty() ? -1 : m_selectedFiles.values().first();
> + if (previouslySelected != -1) {
> + m_selectedFiles.remove(previouslySelected);
> + Q_EMIT dataChanged(index(previouslySelected), index(previouslySelected));
> + }
> + }
> + m_selectedFiles.insert(row);
> + }
> +
> + Q_EMIT dataChanged(index(row), index(row));
> + Q_EMIT selectedFilesChanged();
> +}
> +
> +void FoldersModel::clearSelection()
> +{
> + Q_FOREACH (int selectedFile, m_selectedFiles) {
> + m_selectedFiles.remove(selectedFile);
> + Q_EMIT dataChanged(index(selectedFile), index(selectedFile));
> + }
> + Q_EMIT selectedFilesChanged();
> +}
>
> === modified file 'CameraApp/foldersmodel.h'
> --- CameraApp/foldersmodel.h 2014-07-29 11:57:12 +0000
> +++ CameraApp/foldersmodel.h 2014-08-01 15:50:37 +0000
> @@ -22,27 +22,34 @@
> #include <QtCore/QFileInfo>
> #include <QtCore/QFileSystemWatcher>
> #include <QtCore/QMimeDatabase>
> +#include <QtCore/QSet>
>
> class FoldersModel : public QAbstractListModel
> {
> Q_OBJECT
> Q_PROPERTY (QStringList folders READ folders WRITE setFolders NOTIFY foldersChanged)
> - Q_PROPERTY (QStringList nameFilters READ nameFilters WRITE setNameFilters NOTIFY nameFiltersChanged)
> + Q_PROPERTY (QStringList typeFilters READ typeFilters WRITE setTypeFilters NOTIFY typeFiltersChanged)
> + Q_PROPERTY (QList<int> selectedFiles READ selectedFiles NOTIFY selectedFilesChanged)
> + Q_PROPERTY (bool singleSelectionOnly READ singleSelectionOnly WRITE setSingleSelectionOnly NOTIFY singleSelectionOnlyChanged)
>
> public:
> enum Roles {
> FileNameRole = Qt::UserRole + 1,
> FilePathRole = Qt::UserRole + 2,
> FileUrlRole = Qt::UserRole + 3,
> - FileTypeRole = Qt::UserRole + 4
> + FileTypeRole = Qt::UserRole + 4,
> + SelectedRole = Qt::UserRole + 5
> };
>
> explicit FoldersModel(QObject *parent = 0);
>
> QStringList folders() const;
> void setFolders(const QStringList& folders);
> - QStringList nameFilters() const;
> - void setNameFilters(const QStringList& nameFilters);
> + QStringList typeFilters() const;
> + void setTypeFilters(const QStringList& typeFilters);
> + QList<int> selectedFiles() const;
> + bool singleSelectionOnly() const;
> + void setSingleSelectionOnly(bool singleSelectionOnly);
>
> void updateFileInfoList();
> void insertFileInfo(const QFileInfo& newFileInfo);
> @@ -51,20 +58,26 @@
> QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
> int rowCount(const QModelIndex& parent = QModelIndex()) const;
> Q_INVOKABLE QVariant get(int row, QString role) const;
> + Q_INVOKABLE void toggleSelected(int row);
> + Q_INVOKABLE void clearSelection();
>
> public Q_SLOTS:
> void directoryChanged(const QString &directoryPath);
>
> Q_SIGNALS:
> void foldersChanged();
> - void nameFiltersChanged();
> + void typeFiltersChanged();
> + void selectedFilesChanged();
> + void singleSelectionOnlyChanged();
>
> private:
> QStringList m_folders;
> - QStringList m_nameFilters;
> + QStringList m_typeFilters;
> QFileInfoList m_fileInfoList;
> QFileSystemWatcher* m_watcher;
> QMimeDatabase m_mimeDatabase;
> + QSet<int> m_selectedFiles;
> + bool m_singleSelectionOnly;
> };
>
> #endif // FOLDERSMODEL_H
>
> === modified file 'GalleryView.qml'
> --- GalleryView.qml 2014-07-25 12:44:19 +0000
> +++ GalleryView.qml 2014-08-01 15:50:37 +0000
> @@ -16,7 +16,9 @@
>
> import QtQuick 2.2
> import Ubuntu.Components 1.0
> +import Ubuntu.Content 0.1
> import CameraApp 0.1
> +import "MimeTypeMapper.js" as MimeTypeMapper
>
> Item {
> id: galleryView
> @@ -26,7 +28,9 @@
> property Item currentView: state == "GRID" ? photogridView : slideshowView
> property var model: FoldersModel {
> folders: [application.picturesLocation, application.videosLocation]
> - nameFilters: [ "*.png", "*.jpg", "*.jpeg", "*.PNG", "*.JPG", "*.JPEG", "*.mp4" ]
> + typeFilters: !main.contentExportMode ? [ "image", "video" ]
> + : [MimeTypeMapper.contentTypeToMimeType(main.transferContentType)]
> + singleSelectionOnly: main.transfer.selectionType === ContentTransfer.Single
> }
>
> property bool gridMode: false
> @@ -59,8 +63,12 @@
> model: galleryView.model
> visible: opacity != 0.0
> onPhotoClicked: {
> - slideshowView.showPhotoAtIndex(index);
> - galleryView.gridMode = false;
> + if (main.contentExportMode) {
> + model.toggleSelected(index);
> + } else {
> + slideshowView.showPhotoAtIndex(index);
> + galleryView.gridMode = false;
> + }
> }
> }
>
> @@ -69,7 +77,8 @@
> id: header
> onExit: galleryView.exit()
> actions: currentView.actions
> - gridMode: galleryView.gridMode
> + gridMode: galleryView.gridMode || main.contentExportMode
> + validationVisible: main.contentExportMode && model.selectedFiles.length > 0
> onToggleViews: {
> if (!galleryView.gridMode) {
> // position grid view so that the current photo in slideshow view is visible
> @@ -78,6 +87,15 @@
>
> galleryView.gridMode = !galleryView.gridMode
> }
> + onValidationClicked: {
> + var selection = model.selectedFiles;
> + var urls = [];
> + for (var i=0; i<selection.length; i++) {
> + urls.push(model.get(selection[i], "fileURL"));
> + }
> + model.clearSelection();
> + main.exportContent(urls);
> + }
> }
> }
>
> @@ -93,7 +111,7 @@
> text: i18n.tr("No media available.")
> }
>
> - state: galleryView.gridMode ? "GRID" : "SLIDESHOW"
> + state: galleryView.gridMode || main.contentExportMode ? "GRID" : "SLIDESHOW"
> states: [
> State {
> name: "SLIDESHOW"
>
> === modified file 'GalleryViewHeader.qml'
> --- GalleryViewHeader.qml 2014-07-30 19:29:56 +0000
> +++ GalleryViewHeader.qml 2014-08-01 15:50:37 +0000
> @@ -34,8 +34,10 @@
> property bool shown: true
> property alias actions: actionsDrawer.actions
> property bool gridMode: false
> + property bool validationVisible
> signal exit
> signal toggleViews
> + signal validationClicked
>
> function show() {
> shown = true;
> @@ -83,6 +85,7 @@
> }
> iconName: header.gridMode ? "stock_image" : "view-grid-symbolic"
> onClicked: header.toggleViews()
> + visible: !main.contentExportMode
> }
>
> IconButton {
> @@ -95,6 +98,17 @@
> visible: actionsDrawer.actions.length > 0
> onClicked: actionsDrawer.opened = !actionsDrawer.opened
> }
> +
> + IconButton {
> + objectName: "validationButton"
> + anchors {
> + top: parent.top
> + bottom: parent.bottom
> + }
> + iconName: "ok"
> + onClicked: header.validationClicked()
> + visible: header.validationVisible
> + }
> }
>
> Item {
>
> === modified file 'MimeTypeMapper.js'
> --- MimeTypeMapper.js 2014-07-29 11:57:12 +0000
> +++ MimeTypeMapper.js 2014-08-01 15:50:37 +0000
> @@ -16,22 +16,33 @@
> * along with this program. If not, see <http://www.gnu.org/licenses/>.
> */
>
> +.pragma library
> +.import Ubuntu.Content 0.1 as UbuntuContent
> +
> function startsWith(string, prefix) {
> return string.indexOf(prefix) === 0;
> }
>
> function mimeTypeToContentType(mimeType) {
> if(startsWith(mimeType, "image")) {
> - return ContentType.Pictures;
> + return UbuntuContent.ContentType.Pictures;
> } else if(startsWith(mimeType, "audio")) {
> - return ContentType.Music;
> + return UbuntuContent.ContentType.Music;
> } else if(startsWith(mimeType, "video")) {
> - return ContentType.Videos;
> + return UbuntuContent.ContentType.Videos;
> } else if(startsWith(mimeType, "text/x-vcard")) {
> - return ContentType.Contacts;
> + return UbuntuContent.ContentType.Contacts;
> } else if(startsWith(mimeType, "text")) {
> - return ContentType.Documents;
> + return UbuntuContent.ContentType.Documents;
> } else {
> - return ContentType.Unknown;
> + return UbuntuContent.ContentType.Unknown;
> + }
> +}
> +
> +function contentTypeToMimeType(contentType) {
> + if (contentType === UbuntuContent.ContentType.Pictures) {
> + return "image";
> + } else if (contentType === UbuntuContent.ContentType.Videos) {
> + return "video";
> }
> }
>
> === modified file 'PhotogridView.qml'
> --- PhotogridView.qml 2014-07-29 11:57:12 +0000
> +++ PhotogridView.qml 2014-08-01 15:50:37 +0000
> @@ -15,7 +15,7 @@
> */
>
> import QtQuick 2.2
> -import Ubuntu.Components 1.0
> +import Ubuntu.Components 1.1
> import Ubuntu.Thumbnailer 0.1
> import Ubuntu.Content 0.1
> import "MimeTypeMapper.js" as MimeTypeMapper
> @@ -103,6 +103,13 @@
> visible: isVideo
> }
>
> + Rectangle {
> + anchors.fill: parent
> + color: UbuntuColors.blue
> + opacity: 0.4
> + visible: selected
> + }
> +
> MouseArea {
> anchors.fill: parent
> onClicked: photogridView.photoClicked(index)
>
> === modified file 'Snapshot.qml'
> --- Snapshot.qml 2014-06-04 14:48:22 +0000
> +++ Snapshot.qml 2014-08-01 15:50:37 +0000
> @@ -29,6 +29,8 @@
> shoot.restart()
> }
>
> + visible: false
> +
> Item {
> id: container
> anchors {
> @@ -36,7 +38,6 @@
> bottom: parent.bottom
> }
> width: parent.width
> - visible: false
>
> Image {
> id: snapshot
> @@ -67,11 +68,11 @@
> SequentialAnimation {
> id: shoot
>
> - PropertyAction { target: container; property: "visible"; value: true }
> + PropertyAction { target: snapshotRoot; property: "visible"; value: true }
> PauseAnimation { duration: 150 }
> XAnimator { target: container; to: container.width + shadow.width; duration: UbuntuAnimation.BriskDuration; easing: UbuntuAnimation.StandardEasing}
> PropertyAction { target: snapshot; property: "source"; value: ""}
> - PropertyAction { target: container; property: "visible"; value: false }
> + PropertyAction { target: snapshotRoot; property: "visible"; value: false }
> PropertyAction { target: container; property: "x"; value: 0 }
> }
> }
>
> === added file 'ViewFinderExportConfirmation.qml'
> --- ViewFinderExportConfirmation.qml 1970-01-01 00:00:00 +0000
> +++ ViewFinderExportConfirmation.qml 2014-08-01 15:50:37 +0000
> @@ -0,0 +1,92 @@
> +/*
> + * Copyright 2014 Canonical Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +import QtQuick 2.2
> +import Ubuntu.Components 1.1
> +
> +Item {
> + id: viewFinderExportConfirmation
> +
> + property string mediaPath
> + property Snapshot snapshot
> +
> + function confirmExport(path) {
> + mediaPath = path;
> + snapshot.visible = true;
> + visible = true;
> + }
> +
> + function hide() {
> + mediaPath = "";
> + viewFinderOverlay.visible = true;
> + snapshot.source = "";
> + snapshot.visible = false;
> + visible = false;
> + }
> +
> + visible: false
> +
> + CircleButton {
> + id: retryButton
> + objectName: "retryButton"
> +
> + anchors {
> + right: validateButton.left
> + rightMargin: units.gu(7.5)
> + bottom: parent.bottom
> + bottomMargin: units.gu(6)
> + }
> +
> + iconName: "reload"
> + onClicked: hide()
> + }
> +
> + CircleButton {
> + id: validateButton
> + objectName: "validateButton"
> +
> + width: units.gu(8)
> + anchors {
> + bottom: parent.bottom
> + bottomMargin: units.gu(5)
> + horizontalCenter: parent.horizontalCenter
> + }
> +
> + iconName: "ok"
> + onClicked: {
> + hide();
> + main.exportContent([mediaPath]);
> + }
> + }
> +
> + CircleButton {
> + id: cancelButton
> + objectName: "cancelButton"
> +
> + anchors {
> + left: validateButton.right
> + leftMargin: units.gu(7.5)
> + bottom: parent.bottom
> + bottomMargin: units.gu(6)
> + }
> +
> + iconName: "close"
> + onClicked: {
> + hide();
> + main.cancelExport();
> + }
> + }
> +}
>
> === modified file 'ViewFinderOverlay.qml'
> --- ViewFinderOverlay.qml 2014-07-30 19:29:39 +0000
> +++ ViewFinderOverlay.qml 2014-08-01 15:50:37 +0000
> @@ -288,8 +288,6 @@
> enabled: visible
>
> function shoot() {
> - camera.captureInProgress = true;
> -
> var orientation = Screen.angleBetween(Screen.orientation, Screen.primaryOrientation);
> if (Screen.primaryOrientation == Qt.PortraitOrientation) {
> orientation += 90;
> @@ -304,7 +302,9 @@
> // TODO: there's no event to tell us that the video has been successfully recorder or failed
> }
> } else {
> - shootFeedback.start();
> + if (!main.contentExportMode) {
> + shootFeedback.start();
> + }
> camera.imageCapture.setMetadata("Orientation", orientation);
> var position = positionSource.position;
> if (settings.gpsEnabled && positionSource.valid
> @@ -317,17 +317,12 @@
> camera.imageCapture.setMetadata("GPSTimeStamp", position.timestamp);
> camera.imageCapture.setMetadata("GPSProcessingMethod", "GPS");
> }
> - camera.imageCapture.captureToLocation(application.picturesLocation);
> - }
> - }
> -
> - function completeCapture() {
> - viewFinderOverlay.visible = true;
> - // FIXME: no snapshot is available for videos
> - if (camera.captureMode != Camera.CaptureVideo) {
> - snapshot.startOutAnimation();
> - }
> - camera.captureInProgress = false;
> + if (main.contentExportMode) {
> + camera.imageCapture.captureToLocation(application.temporaryLocation);
> + } else {
> + camera.imageCapture.captureToLocation(application.picturesLocation);
> + }
> + }
> }
>
> function switchCamera() {
> @@ -361,9 +356,7 @@
> target: camera.imageCapture
> onReadyChanged: {
> if (camera.imageCapture.ready) {
> - if (camera.captureInProgress) {
> - controls.completeCapture();
> - } else if (camera.switchInProgress) {
> + if (camera.switchInProgress) {
> controls.completeSwitch();
> }
> }
> @@ -383,6 +376,7 @@
>
> iconName: (camera.captureMode == Camera.CaptureStillImage) ? "camcorder" : "camera-symbolic"
> onClicked: controls.changeRecordMode()
> + enabled: !main.contentExportMode
> }
>
> ShootButton {
>
> === modified file 'ViewFinderView.qml'
> --- ViewFinderView.qml 2014-07-28 12:55:56 +0000
> +++ ViewFinderView.qml 2014-08-01 15:50:37 +0000
> @@ -28,6 +28,7 @@
> property bool optionValueSelectorVisible: false
> property bool touchAcquired: viewFinderOverlay.touchAcquired
> property bool inView
> + property alias captureMode: camera.captureMode
> signal photoTaken
> signal videoShot
>
> @@ -75,7 +76,6 @@
> transparently based on the value. */
> property alias currentZoom: camera.digitalZoom
> property alias maximumZoom: camera.maximumDigitalZoom
> - property bool captureInProgress: false
> property bool switchInProgress: false
>
> imageCapture {
> @@ -86,6 +86,12 @@
> snapshot.source = preview;
> }
> onImageSaved: {
> + if (main.contentExportMode) {
> + viewFinderExportConfirmation.confirmExport(path);
> + } else {
> + viewFinderOverlay.visible = true;
> + snapshot.startOutAnimation();
> + }
> viewFinderView.photoTaken();
> metricPhotos.increment();
> console.log("Picture saved as " + path);
> @@ -96,7 +102,7 @@
> onRecorderStateChanged: {
> if (videoRecorder.recorderState === CameraRecorder.StoppedState) {
> metricVideos.increment()
> - viewFinderOverlay.controls.completeCapture();
> + viewFinderOverlay.visible = true;
> viewFinderView.videoShot();
> }
> }
> @@ -284,4 +290,10 @@
> geometry: viewFinderGeometry
> deviceDefaultIsPortrait: Screen.primaryOrientation === Qt.PortraitOrientation
> }
> +
> + ViewFinderExportConfirmation {
> + id: viewFinderExportConfirmation
> + anchors.fill: parent
> + snapshot: snapshot
> + }
> }
>
> === modified file 'camera-app.qml'
> --- camera-app.qml 2014-07-28 12:55:56 +0000
> +++ camera-app.qml 2014-08-01 15:50:37 +0000
> @@ -16,9 +16,11 @@
>
> import QtQuick 2.2
> import QtQuick.Window 2.0
> +import QtMultimedia 5.0
> import Ubuntu.Components 1.0
> import Ubuntu.Unity.Action 1.1 as UnityActions
> import UserMetrics 0.1
> +import Ubuntu.Content 0.1
>
> Item {
> id: main
> @@ -164,6 +166,46 @@
> }
> }
>
> + property bool contentExportMode: transfer !== null
> + property var transfer: null
> + property var transferContentType: ContentType.Pictures
> +
> + function exportContent(urls) {
> + if (!main.transfer) return;
> +
> + var item;
> + var items = [];
> + for (var i=0; i<urls.length; i++) {
> + item = contentItemComponent.createObject(main.transfer, {"url": urls[i]});
> + items.push(item);
> + }
> + main.transfer.items = items;
> + main.transfer.state = ContentTransfer.Charged;
> + main.transfer = null;
> + }
> +
> + function cancelExport() {
> + main.transfer.state = ContentTransfer.Aborted;
> + main.transfer = null;
> + }
> +
> + Component {
> + id: contentItemComponent
> + ContentItem {
> + }
> + }
> +
> + Connections {
> + target: ContentHub
> + onExportRequested: {
> + if (transferContentType === ContentType.Videos) {
> + viewFinderView.captureMode = Camera.CaptureVideo;
> + } else {
> + viewFinderView.captureMode = Camera.CaptureStillImage;
> + }
> + main.transfer = transfer;
> + }
> + }
>
> Metric {
> id: metricPhotos
>
> === modified file 'camera-apparmor.json'
> --- camera-apparmor.json 2014-07-17 11:03:53 +0000
> +++ camera-apparmor.json 2014-08-01 15:50:37 +0000
> @@ -11,4 +11,4 @@
> "location"
> ],
> "policy_version": 1.2
> -}
Nitpick: this change does nothing, just alter whitespace
> +}
> \ No newline at end of file
>
> === added file 'camera-contenthub.json'
> --- camera-contenthub.json 1970-01-01 00:00:00 +0000
> +++ camera-contenthub.json 2014-08-01 15:50:37 +0000
> @@ -0,0 +1,5 @@
> +{
> + "source": [
> + "pictures"
> + ]
> +}
>
> === modified file 'cameraapplication.cpp'
> --- cameraapplication.cpp 2014-07-29 18:08:21 +0000
> +++ cameraapplication.cpp 2014-08-01 15:50:37 +0000
> @@ -123,3 +123,11 @@
> dir.mkpath(location);
> return location;
> }
> +
> +QString CameraApplication::temporaryLocation() const
> +{
> + QString location = QStandardPaths::standardLocations(QStandardPaths::TempLocation).at(0);
Unlikely, but the list returned by this function can be empty, so at(0) will crash the app. Please check or use value()
> + QDir dir;
> + dir.mkpath(location);
> + return location;
> +}
>
> === modified file 'cameraapplication.h'
> --- cameraapplication.h 2014-07-02 15:43:31 +0000
> +++ cameraapplication.h 2014-08-01 15:50:37 +0000
> @@ -31,6 +31,7 @@
> Q_PROPERTY(bool desktopMode READ isDesktopMode CONSTANT)
> Q_PROPERTY(QString picturesLocation READ picturesLocation CONSTANT)
> Q_PROPERTY(QString videosLocation READ videosLocation CONSTANT)
> + Q_PROPERTY(QString temporaryLocation READ temporaryLocation CONSTANT)
>
> public:
> CameraApplication(int &argc, char **argv);
> @@ -39,6 +40,7 @@
> bool isDesktopMode() const;
> QString picturesLocation() const;
> QString videosLocation() const;
> + QString temporaryLocation() const;
>
> private:
> QScopedPointer<QQuickView> m_view;
>
> === modified file 'manifest.json'
> --- manifest.json 2014-07-10 14:27:45 +0000
> +++ manifest.json 2014-08-01 15:50:37 +0000
> @@ -5,7 +5,8 @@
> "hooks": {
> "camera": {
> "apparmor": "camera-apparmor.json",
> - "desktop": "@DESKTOP_FILE@"
> + "desktop": "@DESKTOP_FILE@",
> + "content-hub": "camera-contenthub.json"
> }
> },
> "icon": "@CAMERA_ICON@",
> @@ -20,4 +21,4 @@
> "x-test": {
> "autopilot": "@AUTOPILOT_DIR@"
> }
> -}
> +}
More unnecessary whitespace changes
> \ No newline at end of file
>
--
https://code.launchpad.net/~fboucault/camera-app/content_source/+merge/229250
Your team Ubuntu Phablet Team is subscribed to branch lp:camera-app.
More information about the Ubuntu-reviews
mailing list